【问题标题】: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。这是一个非常糟糕的资源。

标签: sql between


【解决方案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 种人...stackoverflow.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

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

          【讨论】:

          • 这纯粹是个人喜好。我不认为“
          • 我假设您的意思是 '>=',因为 '
          猜你喜欢
          • 2020-10-04
          • 1970-01-01
          • 2014-11-15
          • 2016-09-22
          • 2016-06-02
          • 2011-02-15
          • 2016-05-03
          • 1970-01-01
          • 2021-01-14
          相关资源
          最近更新 更多