当我们可以不用 BETWEEN 运算符时,为啥还要使用它呢?
Posted
技术标签:
【中文标题】当我们可以不用 BETWEEN 运算符时,为啥还要使用它呢?【英文标题】:Why use the BETWEEN operator when we can do without it?当我们可以不用 BETWEEN 运算符时,为什么还要使用它呢? 【发布时间】:2009-12-25 08:42:26 【问题描述】:如下面的两个查询所示,我们发现它们都运行良好。然后我很困惑为什么我们应该使用 BETWEEN 因为我发现 BETWEEN 在不同数据库中的行为不同,如 w3school
SELECT *
FROM employees
WHERE salary BETWEEN 5000 AND 15000;
SELECT *
FROM employees
WHERE salary >= 5000
AND salary <= 15000;
【问题讨论】:
列出的 URL 没有引用具有不同属性的特定 DBMS。 SQL 标准要求范围包括两个端点;任何不遵循的 DBMS 基本上都有一个错误。如果没有具体细节,我认为w3schools.com 的断言是没有根据的。 远离 w3school。这是一个非常糟糕的资源。 【参考方案1】:BETWEEN
可以帮助避免不必要的重新计算表达式:
SELECT AVG(RAND(20091225) BETWEEN 0.2 AND 0.4)
FROM t_source;
---
0.1998
SELECT AVG(RAND(20091225) >= 0.2 AND RAND(20091225) <= 0.4)
FROM t_source;
---
0.3199
t_source
只是一个带有1,000,000
记录的虚拟表。
当然,这可以使用子查询来解决,但在mysql
中效率较低。
当然,BETWEEN
更具可读性。在查询中使用它需要3
次才能永远记住语法。
在SQL Server
和MySQL
中,LIKE
与非前导常量'%'
是一对>=
和<
的简写:
SET SHOWPLAN_TEXT ON
GO
SELECT *
FROM master
WHERE name LIKE 'string%'
GO
SET SHOWPLAN_TEXT OFF
GO
|--Index Seek(OBJECT:([test].[dbo].[master].[ix_name_desc]), SEEK:([test].[dbo].[master].[name] < 'strinH' AND [test].[dbo].[master].[name] >= 'string'), WHERE:([test].[dbo].[master].[name] like 'string%') ORDERED FORWARD)
不过,LIKE
语法更清晰。
【讨论】:
使用它的好理由,但非常具体(例如,用于与当前时间戳进行比较)并且仅限于 where 中的一个表达式,这可能会产生更多错误。这些东西必须作为参数传递给查询。 BETWEEN 的性质使其适用于刚性范围。但如果这是可以接受的,我们将获得更好的性能。如果我们需要更多条件的灵活范围,我们几乎不能忽略符号(、>= 左右)。感谢@Quassnio 在查询时间方面进行比较分析。@sangam
: 这不是查询时间,是查询正确性:)
@Quassnoi,非常感谢您的纠正。我也会编辑我的答案。
此外,上述评论将是: BETWEEN 的性质使其适用于刚性范围。但如果这是可以接受的,我们就会得到更高的准确性。如果我们需要更多条件的灵活范围,我们几乎不能忽略符号(、>= 左右)。感谢@Quassnio 在查询正确性方面进行比较分析。【参考方案2】:
当比较的表达式是一个复杂的计算而不仅仅是一个简单的列时,使用 BETWEEN 有额外的优点;它节省了写出那个复杂的表达式两次。
【讨论】:
【参考方案3】:T-SQL 中的 BETWEEN 支持 NOT 运算符,因此您可以使用类似的结构
WHERE salary not between 5000 AND 15000;
在我看来,这对人类来说更清楚
WHERE salary < 5000 OR salary > 15000;
最后,如果你只输入一次列名,你犯错的机会就会减少
【讨论】:
关于“对人类更清晰”:“在空间分隔(两点、物体等)”。不包括在 ANSI 标准中。来自dictionary.reference.com/browse/BETWEEN 的引用? . NOT BETWEEN 需要更多的心理杂技。 您的意思是“WHERE 薪水 15000” @bniwredyc:好的。在这种情况下,我更喜欢数学符号。有 10 种人...***.com/questions/234075/… :-)【参考方案4】:带有“between”的版本更容易阅读。如果我要使用第二个版本,我可能会把它写成
5000 <= salary and salary <= 15000
出于同样的原因。
【讨论】:
+1 范围检查非常容易阅读,只需小于! 易读,但不易理解。想象一下,您将 BETWEEN 用于 STRING 或 DATETIME 值... 对不起,Kev,但我不认为这是一个错字。像现在这样没有意义...... 我认为你的意思是 5000 这确实是我的意思,所以这就是我写的。我也看不出将“介于”与数字类型以外的类型一起使用的问题是什么,只要它们有顺序。【参考方案5】:我投票给@Quassnoi - 正确性是一大胜利。
我通常发现文字比 、>=、!= 等语法符号更有用。是的,我们需要(更好、更准确)的结果。至少我摆脱了视觉上误解和恢复符号含义的可能性。如果您使用 = [视觉错误解释?]。希望我清楚。
我们不是在缩短代码(同时让它看起来更高级),这意味着更简洁和易于维护吗?
SELECT *
FROM emplyees
WHERE salary between 5000 AND 15000;
SELECT *
FROM emplyees
WHERE salary >= 5000 AND salary <= 15000;
第一个查询仅使用 10 个单词,第二个使用 12 个!
【讨论】:
【参考方案6】:就个人而言,我不会使用BETWEEN
,只是因为在您给定的示例中,似乎没有明确定义它是否应该包含或排除用于限制条件的值:
SELECT *
FROM emplyees
WHERE salary between 5000 AND 15000;
范围可以包括5000和15000,或者可以排除它们。
从句法上讲,我认为应该排除它们,因为值本身 不是 在给定数字之间。但我的观点恰恰是这样,而使用诸如>=
之类的运算符是非常具体的。并且不太可能在数据库之间或相同的增量/版本之间发生变化。
编辑以回应 Pavel 和 Jonathan 的 cmets。
正如 Pavel 所指出的,早在 1992 年,ANSI SQL (http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt) 就要求端点应在返回日期内考虑,并等同于 X >= lower_bound AND X <= upper_bound
:
8.3
Function Specify a range comparison. Format <between predicate> ::= <row value constructor> [ NOT ] BETWEEN <row value constructor> AND <row value constructor> Syntax Rules 1) The three <row value constructor>s shall be of the same degree. 2) Let respective values be values with the same ordinal position in the two <row value constructor>s. 3) The data types of the respective values of the three <row value constructor>s shall be comparable. 4) Let X, Y, and Z be the first, second, and third <row value con- structor>s, respectively. 5) "X NOT BETWEEN Y AND Z" is equivalent to "NOT ( X BETWEEN Y AND Z )". 6) "X BETWEEN Y AND Z" is equivalent to "X>=Y AND X<=Z".
【讨论】:
SQL Server、Oracle、MySQL、Postgres...都认为端点具有包容性。 SQL 标准要求端点包含在范围内。 OMG Ponies:好的,但不是自然语言规则。而这一事实与关于“更具可读性的代码”的建议相冲突。 我很抱歉,@Pavel 和@Jonathan,我不知道它在 ANSI SQL 中的定义;并在一些无知的情况下提供了我的答案,我感谢您的更正。已编辑。 另外,@Pavel 和 Jonathan,+1 帮助我理顺我 =)【参考方案7】:如果端点是包容性的,那么BETWEEN
是首选语法。
对列的引用越少,意味着当事情发生变化时需要更新的地方就越少。这是工程原理,更少的东西意味着更少的东西可以破坏。
这也意味着有人为包括 OR 之类的东西放错括号的可能性较小。即:
WHERE salary BETWEEN 5000 AND (15000
OR ...)
...如果将括号放在 BETWEEN 语句的 AND 部分周围,则会出现错误。对战:
WHERE salary >= 5000
AND (salary <= 15000
OR ...)
...只有当有人查看查询返回的数据时,您才会知道存在问题。
【讨论】:
带括号的例子很好。但是关于包容性之间,它实际上在不同的数据库中表现不同,正如我从w3schools.com/sql/sql%5Fbetween.asp发现的那样 这是关于常见的括号格式规则,不仅适用于 BETWEEN 语句。您的查询的简单格式文本properry,没有问题。 @Thunder:如果您查看各自的数据库文档,您会发现它在 Oracle、SQL Server、MySQL、Postgres、SQLite 中始终如一地实现(即 ANSI-92)。【参考方案8】:在语义上,这两个表达式具有相同的结果。
但是,BETWEEN
是单个谓词,而不是与 AND
结合的两个比较谓词。根据您的 RDBMS 提供的优化器,单个谓词可能比两个谓词更容易优化。
虽然我希望大多数现代 RDBMS 实现应该同样优化这两个表达式。
【讨论】:
【参考方案9】:如果是更糟糕的
SELECT id FROM entries
WHERE
(SELECT COUNT(id) FROM anothertable WHERE something LEFT JOIN something ON...)
BETWEEN entries.max AND entries.min;
用你的语法重写这个而不使用临时存储。
【讨论】:
【参考方案10】:我最好使用第二个,因为你总是知道它是
【讨论】:
如果您正确了解 SQL,您就知道 BETWEEN 做了什么。否则,你就是一个在 SQL 中乱搞的程序员 - 让数据库开发人员为你编写 SQL! 我应该解雇当前的程序员吗?或者我可以让他使用他理解的语法,而不是让一个新人来做这项工作吗?【参考方案11】:在 SQL 中,我同意 BETWEEN
大部分是不必要的,并且可以在语法上用 5000 <= salary AND salary <= 15000
进行模拟。它也是有限的;我经常想应用一个包含的下限和一个独占的上限:@start <= when AND when < @end
,而 BETWEEN
则无法做到这一点。
如果要测试的值是复杂表达式的结果,那么 BETWEEN 很方便。
如果 SQL 和其他语言能够效仿 Python 使用正确的数学符号,那就太好了:5000 <= salary <= 15000
。
让您的代码更具可读性的一个小技巧:使用 和 >=。
【讨论】:
这纯粹是个人喜好。我不认为“ 我假设您的意思是 '>=',因为 '以上是关于当我们可以不用 BETWEEN 运算符时,为啥还要使用它呢?的主要内容,如果未能解决你的问题,请参考以下文章
当我们可以在 awakeFromNib 中转储所有内容时,为啥还要使用 init(coder)?
当我们已经有 CROSS_COMPILE= 时为啥还要有 ARCH=
Exchange Web Service 与 Exchange ActiveSync(或者当您可以免费获得奶牛时,为啥还要购买牛奶?)