, =和 b : 如果 a > b 为真没有 a' b没有 b' > b满足a > b' a @ a 为真 a @>= b : -6ren">
gpt4 book ai didi

mysql - 为什么SQL中没有 "first greater/less than [or equal to]"比较运算符?

转载 作者:IT老高 更新时间:2023-10-29 00:07:06 25 4
gpt4 key购买 nike

我正在考虑在 SQL 中提出 4 个新的比较运算符。这些类似于 > , < , >=<=运算符,但仅当每个操作数的值是满足不等式的所有值中的一个 时才为真。最近 到另一个操作数的值。由于一个值​​几乎是 另一个值,我得出的结论是(在意识到没有 first 关键字,并在丢弃 unique 关键字之后)定义这 4 个新运算符是一个不错的选择:

  • a @> b : 如果 a > b 为真没有 a' < a满足a' > b没有 b' > b满足a > b'
  • a @< b : 如果 b @> a 为真
  • a @>= b : 如果 a ≥ b 为真没有 a' < a满足a' ≥ b没有 b' > b满足a ≥ b'
  • a @<= b : 如果 b @>= a 为真

  • 问题是: 像这样的运营商不存在有什么好的理由吗?

    (2014-03-20) 我重新表述了这个问题,因为上面的表述显然不够清楚:

    有没有理由不存在这样的运营商?

    以下示例旨在作为找出 @... 问题所在的起点。运营商可能会撒谎。我将使用 3 个 MySQL 表:
    create table ta (id int auto_increment, ca char, primary key(id), unique index(ca));
    create table tb (id int auto_increment, cb char, primary key(id), index(cb));
    create table tc (id int auto_increment, cc char, primary key(id));
    insert into ta (ca) values ('A'),('E'),('I'),('O'),('U');
    insert into tb (cb) values ('C'),('D'),('E'),('F'),('F'),('M'),('N'),('O'),('Z');
    insert into tc (cc) values ('C'),('D'),('E'),('F'),('F'),('M'),('N'),('O'),('Z');

    示例#1

    当列具有唯一值时, @... 的效果可以通过将查询或子查询的输出限制为 1 行来获得运算符,尽管语法有点笨拙:
    ?> select * from ta where ca @> 'B'; -- currently not valid, equivalent to:
    !> select * from ta where ca > 'B' order by ca limit 1;
    +----+------+
    | id | ca |
    +----+------+
    | 2 | E |
    +----+------+

    ( limit 1 特定于 MySQL、MariaDB、PostgreSQL 等,其他 RDBMS 有 select top 1where rownum = 1 等)

    表中 ta我们在列 ca 上有一个唯一索引.可以利用该索引来获取所选值 同速至于 ca = 'E' .优化器可能会意识到这一点,但如果没有,则可能会为从选定值开始的不需要的扫描设置数据结构(MySQL 的 explain 说这是一个 range 类型的查询)。

    示例#2

    当列具有非唯一值时,限制输出行是无用的,语法变得更加笨拙:
    ?> select * from tb where cb @> 'E'; -- currently not valid, equivalent to:
    !> select * from tb where cb = (select min(cb) from tb where cb > 'E');
    +----+------+
    | id | cb |
    +----+------+
    | 4 | F |
    | 5 | F |
    +----+------+

    幸运的是,如果我正确读取了 explain 的输出, MySQL 足够聪明,可以优化子查询,但如果不是,索引将被使用两次而不是一次。

    在表 tc的情况下, 列 cc 上没有索引, MySQL 进行两次表扫描。这是可以理解的,因为单个表扫描意味着使用未知数量的存储来存储临时结果。

    示例 #3

    假设您需要由一个值及其后继值组成的所有对:
    ?> select t1.ca as c1, t2.ca as c2
    from ta t1
    join ta t2 on t1.ca @< t2.ca; -- currently not valid, equivalent to:
    !> select t1.ca as c1, t2.ca as c2
    from ta t1
    join ta t2 on t2.ca = (select min(ca) from ta where ca > t1.ca);
    +------+------+
    | c1 | c2 |
    +------+------+
    | A | E |
    | E | I |
    | I | O |
    | O | U |
    +------+------+

    如果我读了 explain 的输出正确的是,MySQL 优化器不能没有相关的子查询,而我们人类会更清楚。也许在 @... 的特殊处理的帮助下运算符(operator)接入,优化器会做一次扫描吗?

    示例 #4

    这很相似,但跨越两个表,其中一个具有非唯一索引:
    ?> select * from ta join tb on ca @< cb; -- currently not valid, equivalent to:
    !> select * from ta join tb on cb = (select min(cb) from tb where cb > ca);
    +----+------+----+------+
    | id | ca | id | cb |
    +----+------+----+------+
    | 1 | A | 1 | C |
    | 2 | E | 4 | F |
    | 2 | E | 5 | F |
    | 3 | I | 6 | M |
    | 4 | O | 9 | Z |
    | 5 | U | 9 | Z |
    +----+------+----+------+

    在这里,MySQL 优化器也不会优化掉子查询,尽管(可能带有 @< 的提示)它可以。

    示例#5

    (添加于 2014-03-20。) @...运营商似乎在任何地方都有意义 @ ——少同行做。这是 where 中表达式的人为示例健康)状况:
    ?> select * from ta join tb
    where round((ascii(ca)+ascii(cb))/2) @> ascii('E');
    -- currently not valid, equivalent to:
    !> select * from ta join tb
    where round((ascii(ca)+ascii(cb))/2) = (
    select min(round((ascii(ca)+ascii(cb))/2)) from ta, tb
    where round((ascii(ca)+ascii(cb))/2) > ascii('E')
    );
    +----+------+----+------+
    | id | ca | id | cb |
    +----+------+----+------+
    | 3 | I | 1 | C |
    | 2 | E | 4 | F |
    | 2 | E | 5 | F |
    +----+------+----+------+

    示例 #6

    ...这是另一个例子,这次是 select表达:
    ?> select *, cb @< ca
    from tb, ta; -- currently not valid, equivalent to:
    !> select *, ifnull(cb = (select max(cb) from tb where cb < ca), 0) as 'cb @< ca'
    from tb, ta;
    +----+------+----+------+----------+
    | id | cb | id | ca | cb @< ca |
    +----+------+----+------+----------+
    | 1 | C | 1 | A | 0 |
    | 1 | C | 2 | E | 0 |
    | 1 | C | 3 | I | 0 |
    | 1 | C | 4 | O | 0 |
    | 1 | C | 5 | U | 0 |
    | 2 | D | 1 | A | 0 |
    | 2 | D | 2 | E | 1 |
    | -- (omitting rows with cb @< ca equal to 0 from here on)
    | 4 | F | 3 | I | 1 |
    | 5 | F | 3 | I | 1 |
    | 7 | N | 4 | O | 1 |
    | 8 | O | 5 | U | 1 |

    我知道以下注意事项:

    警告 #1
    @...运算符是“非本地的”,因为它们需要了解其操作数的所有可能值。在上述示例中显示的所有条件下,这似乎不是问题,但在其他地方可能是问题(尽管我还没有找到无法通过附加子查询解决的示例)。

    警告 #2
    @...运营商,不像他们的 @ -less 对应项,不可传递。他们与 <> 共享此属性运营商,虽然。

    警告 #3

    充分利用 @...运算符可能意味着引入新的索引和表访问类型(如示例中所述)。

    请注意,这个问题并不是讨论的起点。我正在寻找类似 @... 的原因运算符不在标准中,也不在我所知的任何 SQL 方言中 - 我希望这些原因与我忽略的这些运算符的定义和/或实现的某些问题有关。

    我知道一个原因是“奥卡姆 Razor ”(pluralitas non est ponenda sine necessitate),但是,正如我在上面试图展示的,这里的 pluralitas 也带来了一些优势(简洁和易于优化)。我正在寻找更有力的理由。

    (2014-03-31) @> , @< , @>=@<=可以变成 |> , |< , |>=|<=或类似(阅读:首先更大/更少 [等于]),以免与 @ 的既定用法发生冲突标识符前缀。

    最佳答案

    我很困惑这是否是这个问题的合适论坛。但是,这些运算符不存在的原因是它们不是特别有用,其他 ANSI SQL 功能取而代之。

    一、on中的比较运算符在我知道的每个数据库中,子句都可以在 where 中找到。和 case条款。目前尚不清楚这些运算符将如何在这些上下文中使用。

    其次,运营商没有指定在关系的情况下该做什么。返回所有行?但是,当这种运算符的用户只期望一行时,这将返回多行。

    三、ANSI标准功能,如row_number()可以产生等价的结果。虽然它可能不是这个特定问题的最佳选择,但它更通用。和标准。

    顺便说一句,Postgres 有一个很好的功能 distinct on() ,这通常比等效的解析函数更有效。

    我偷偷想要一个新的join类型, lookup join ,如果有多个记录匹配,那将会失败。但是,我不太确定是否应该为此目的更改整个语言。

    关于mysql - 为什么SQL中没有 "first greater/less than [or equal to]"比较运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22438273/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com