当我们可以不用 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 ServerMySQL 中,LIKE 与非前导常量'%' 是一对&gt;=&lt; 的简写:

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,或者可以排除它们。

从句法上讲,我认为应该排除它们,因为值本身 不是 给定数字之间。但我的观点恰恰是这样,而使用诸如&gt;= 之类的运算符是非常具体的。并且不太可能在数据库之间或相同的增量/版本之间发生变化。


编辑以回应 Pavel 和 Jonathan 的 cmets。

正如 Pavel 所指出的,早在 1992 年,ANSI SQL (http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt) 就要求端点应在返回日期内考虑,并等同于 X &gt;= lower_bound AND X &lt;= 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 &lt;= salary AND salary &lt;= 15000 进行模拟。它也是有限的;我经常想应用一个包含的下限和一个独占的上限:@start &lt;= when AND when &lt; @end,而 BETWEEN 则无法做到这一点。

如果要测试的值是复杂表达式的结果,那么 BETWEEN 很方便。

如果 SQL 和其他语言能够效仿 Python 使用正确的数学符号,那就太好了:5000 &lt;= salary &lt;= 15000

让您的代码更具可读性的一个小技巧:使用 和 >=。

【讨论】:

这纯粹是个人喜好。我不认为“ 我假设您的意思是 '>=',因为 '

以上是关于当我们可以不用 BETWEEN 运算符时,为啥还要使用它呢?的主要内容,如果未能解决你的问题,请参考以下文章

当我们可以在 awakeFromNib 中转储所有内容时,为啥还要使用 init(coder)?

当我们只能使用 NSObject 时,为啥还要使用 id?

当我们已经有 CROSS_COMPILE= 时为啥还要有 ARCH=

Oracle Between(范围)子句

Oracle Between(范围)子句

Exchange Web Service 与 Exchange ActiveSync(或者当您可以免费获得奶牛时,为啥还要购买牛奶?)