为什么SQL中没有“第一个大于/小于[或等于]”的比较运算符?

时间:2014-03-16 14:40:39

标签: mysql sql

3 个答案:

答案 0 :(得分:12)

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

首先,on子句中的比较运算符在我知道的每个数据库中都可用于wherecase子句中。目前还不清楚这些运营商将如何在这些背景下使用。

其次,运营商没有具体说明在关系的情况下该做什么。返回所有行?但是当这样的运算符的用户只期望一行时,这会返回多行。

第三,ANSI标准功能(例如row_number())可以生成相同的结果。虽然它可能不是这个特定问题的最佳选择,但它更为通用。标准。

顺便说一句,Postgres具有distinct on()的良好功能,通常比等效的解析功能更有效。

我秘密地希望新的join类型lookup join,如果匹配多条记录,则会失败。但是,我不太确定为此目的应该改变整个语言。

答案 1 :(得分:8)

暂时搁置你提议的补充的优点,你实际上只有一个问题:

  

问题是:为什么像这样的运营商已经存在,还有一些很好的理由吗?

任何其他缺席功能的原因相同:因为还没有人实现它。

现在,由于以下各项的结合,没有人实现它的原因很可能是没有人觉得需要一个特殊的操作员,这是因为:

  • 有用的情况并不常见,并且每个可以想象的任务用新操作符污染语言都不是一个好主意。
  • 使用现有语法实现相同任务的变通方法既简单又充足。
  • 如果人们确实认为该功能值得实施,他们可能会使用与使用@作为运营商一部分的语法不同的语法。

当然,简洁是很好的,但这似乎并不是SQL的目标(否则SQL将以relational algebra表示法编写)。

非标准条款,如LIMIT(MySQL,PostgreSQL,SQLite)或TOP(Microsoft,Sybase)或ROWNUM(Oracle)或FIRST(Informix, InterBase)足以满足大多数用户的需求。

使用有序窗口函数的标准语法实际上是SQL:2003规范定义的解决方案。我意识到窗口函数是not supported by MySQL yet,但几乎所有其他品牌的RDBMS都支持它们。

如果您建议专门为MySQL添加此功能,最好使用标准语法使其与其他品牌更兼容,而不是引入新的非标准语法。


现在回答你的另一个问题:

  

我正在寻找这些@运营商可能遇到的真正问题。

立即浮现在脑海中:它不是通用的。

它处理只需要紧跟比较操作数后面的单行的情况。但它并没有处理有序窗口函数可以满足的许多其他情况:

  • 在窗口中返回下一个两个行。
  • 在窗口中返回 last 行。
  • rank 而不是按行号返回前三行。

它还引入了一个新的标点符号,它在标准SQL中没有先例,并且可能与某些供应商的添加冲突,例如在MySQL中添加前缀用户变量或在Microsoft SQL Server中添加前缀参数。


我在PostgreSQL 8.4中测试了你的例子,supports window functions。我知道这不是PostgreSQL的当前版本,但它是CentOS repo中的默认版本,并且它足以演示窗口函数。

示例#1

select * 
from (select *, row_number() over (order by ca) as rn from ta where ca > 'B') as t
where rn = 1;

 id | ca | rn 
----+----+----
  2 | E  |  1

示例#2

select * 
from (select *, rank() over (order by cb) as rk from tb where cb > 'E') as t
where rk = 1;

 id | cb | rk 
----+----+----
  5 | F  |  1
  4 | F  |  1

示例#3

select t1.ca as c1, t2.ca as c2
from (select ca, row_number() over (order by ca) AS rn from ta) as t1
join (select ca, row_number() over (order by ca) AS rn from ta) as t2
  on t1.rn+1 = t2.rn;

 c1 | c2 
----+----
 A  | E
 E  | I
 I  | O
 O  | U

示例#4

select *
from (select ta.id, ta.ca, tb.id, tb.cb, 
    rank() over (partition by ca order by cb) AS rk 
    from ta join tb on ca < cb) as t
where rk = 1;

 id | ca | id | cb | rn 
----+----+----+----+----
  1 | A  |  1 | C  |  1
  2 | E  |  5 | F  |  1
  2 | E  |  4 | F  |  1
  3 | I  |  6 | M  |  1
  4 | O  |  9 | Z  |  1
  5 | U  |  9 | Z  |  1

答案 2 :(得分:1)

对于像这样的地方,也许这不是一个真正的问题。我必须承认,它确实听起来像一个很好的功能,但还有其他方法可以做到这一点。 (虽然我想其他许多函数都已经添加了其他功能!)

我认为这样的事情的真正答案可能是:

:一种。需求 - 如果开发人员觉得很少有人会使用它们,那么开发人员是否值得将这样的函数添加到SQL中?

<强> B中。功能 - 它实际上是否允许开发人员做得更多,还是只是达到同一目标的另一种方式?

<强>℃。懒惰 - 他们真的会被这样的事情困扰吗?

获得答案的最佳方法是将其提交给他们的开发团队,看看他们的回答是什么,如果有足够多的人可以参与要求实现这样的事情,那么它可以......多数人的力量!

相关问题