为什么我们可以不使用BETWEEN运算符,它有什么作用?

16

从下面两个查询结果可以看出,它们都很好地工作。 那么我很困惑为什么我们需要使用BETWEEN,因为我发现在不同的数据库中,BETWEEN的行为是不同的,这可以在w3school上找到。

SELECT *
FROM employees
WHERE salary BETWEEN 5000 AND 15000;

SELECT *
FROM employees
WHERE salary >= 5000
AND salary <= 15000;

2
所列出的URL未引用具有不同属性的特定DBMS。SQL标准要求范围包括两个端点;任何不遵循此规则的DBMS基本上都存在漏洞。如果没有具体细节,我认为http://www.w3schools.com/上的声明是毫无根据的。 - Jonathan Leffler
4
远离w3school。这是一个信息非常不准确的资源。 - Johan
11个回答

32

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更易读。将其用于查询需要记住语法,而且需要三次操作。

SQL ServerMySQL中,对常量使用非前导'%'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子句中的一个表达式,这可能会产生更多的错误。这些东西必须作为参数传递到查询中。 - ThinkJet
BETWEEN的特性使其在严格范围内非常有用。但如果可以接受,我们可以获得更好的性能。如果我们需要更灵活的范围和更多的条件限制,我们几乎不能忽略符号(<、<=、>、>=等)。感谢@Quassnio以查询时间为比较分析的贡献。 - sangam
@sangam:这不是查询时间,而是查询正确性 :) - Quassnoi
@Quassnoi,非常感谢您的纠正。我也会编辑我的答案。 - sangam
此外,上述评论将是: BETWEEN 的性质使其在严格范围内非常有用。但如果可以接受,我们可以获得更高的准确性。如果我们需要更灵活的范围和更多的条件限制,我们几乎不能忽略符号(<、<=、>、>= 或其他)。感谢 @Quassnio 将比较分析放在查询正确性方面。 - sangam

16

当进行比较的表达式是复杂计算而不仅仅是简单列时,使用BETWEEN具有额外的优点;它可以避免重复编写这个复杂的表达式。


5
“between” 版本更易于阅读。如果我要使用第二个版本,我可能会这样写:
5000 <= salary and salary <= 15000

出于同样的原因。

使用仅小于号的范围检查更容易阅读!+1 - Andomar
易于阅读,但不易于理解。想象一下,您使用BETWEEN来处理字符串或日期时间值... - ThinkJet
1
抱歉,Kev,但我认为那不是一个打字错误。现在的样子没有意义... - Radu094
1
我认为你的意思是:5000 <= 薪水 and 薪水 <= 15000应该使用BETWEEN。 :-) - Bob Jarvis - Слава Україні
那确实是我所想的,所以那就是我写的内容。只要它们有一个顺序,我也不认为在除了数值类型之外的其他类型中使用“between”会有什么问题。 - Rich

5

T-SQL中的BETWEEN支持NOT运算符,因此您可以使用以下结构:

WHERE salary not between 5000 AND 15000; 

在我看来,相较于机器,这更容易让人理解。
WHERE salary < 5000 OR salary > 15000;

最后,如果您只输入列名一次,则减少犯错的机会


关于“更易于人类阅读”:指在分隔符(两个点、对象等)之间。这不包括 ANSI 标准。引自http://dictionary.reference.com/browse/BETWEEN?。NOT BETWEEN 要求进行更多的思维运算。 - ThinkJet
2
你的意思是 "WHERE salary < 5000 OR salary > 15000"。 - Doc Brown
1
@bniwredyc:好的。在这种情况下,我更喜欢使用数学符号。有10种人... http://stackoverflow.com/questions/234075/what-is-your-best-programmer-joke/234128#234128 :-) - ThinkJet

2
个人而言,我不会使用BETWEEN,因为在你给出的例子中似乎没有明确的定义它是否应该包括或排除用于界定条件的值。
SELECT *
FROM emplyees
WHERE salary between 5000 AND 15000;

范围可能包括5000和15000,也可能不包括它们。从句法上讲,我认为应该排除它们,因为这些值本身并不在给定的数字之间。但这只是我的观点,而使用像">="这样的运算符则非常具体。而且在不同的数据库或同一数据库的增量/版本之间更不可能改变。
根据 Pavel 和 Jonathan 的评论进行了编辑。
正如 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".

3
SQL Server、Oracle、MySQL和PostgreSQL都将端点视为包含在内。 - OMG Ponies
4
SQL标准要求范围包括端点。 - Jonathan Leffler
OMG Ponies: 好吧,但不符合自然语言规则。这事实与“更易读的代码”的建议相冲突。 - ThinkJet
很抱歉,@Pavel和@Jonathan,我不知道它在ANSI SQL中的定义,所以犯了一些错误。感谢你们纠正我的错误。我已经编辑了回答。 - David Thomas
另外,@Pavel和Jonathan,感谢你们的帮助,让我明白了 =) - David Thomas
只要学会如何使用语言... '==' Vs '=' 对于 C 程序员来说一开始看起来很困惑,'==' Vs '===' 在 JavaScript 中也是如此... 但这并不意味着你不应该学习并使用它们。 - Mr. Boy

2

我投票支持@Quassnoi-正确性是一个巨大的胜利。

我通常发现文字比诸如<、<=、>、>=、!=等语法符号更有用。是的,我们需要(更好、准确)的结果。至少我可以摆脱视觉上误解和反转符号含义的可能性。如果您使用<=并从选择查询中得到逻辑不正确的输出,您可能会浪费一些时间,并得出结论,即您在<=的位置上写了>= [视觉误解?]。希望我说得清楚。

我们不是在缩短代码(同时使其看起来更高级),这意味着更简洁易于维护吗?

SELECT * 
FROM emplyees 
WHERE salary between 5000 AND 15000; 



SELECT * 
FROM emplyees 
WHERE salary >= 5000 AND salary <= 15000; 

第一次查询只使用了10个单词,而第二次则使用了12个单词!


1
如果端点是包含的,则BETWEEN是首选语法。
对列的引用越少,意味着在事物发生变化时需要更新的位置就越少。这是工程原则,即较少的东西意味着较少的东西会出错。
这也意味着更少的可能性让某人在像包括OR这样的事情时放错括号。例如:
WHERE salary BETWEEN 5000 AND (15000
  OR ...)

如果你在BETWEEN语句的AND部分加上括号,就会出现错误。相比之下:

WHERE salary >= 5000
 AND (salary <= 15000
  OR ...)

...只有当有人审查从查询返回的数据时,您才会知道问题存在。


括号的例子很好。但是关于包含Between,我从http://www.w3schools.com/sql/sql%5Fbetween.asp发现它在不同的数据库中实际上表现不同。 - Thunder
这是关于常见的括号格式规则,不仅适用于BETWEEN语句。正确地简化查询文本格式,就没有问题了。 - ThinkJet
@Thunder:如果你查看各自的数据库文档,你会发现它在Oracle、SQL Server、MySQL、Postgres、SQLite中都得到了一致的实现(符合ANSI-92标准)。 - OMG Ponies

0

如果它更糟糕

  SELECT id FROM entries 
  WHERE 
     (SELECT COUNT(id) FROM anothertable WHERE something LEFT JOIN something ON...) 
     BETWEEN entries.max AND entries.min;

请使用您的语法重写此代码,而不使用临时存储。


0
从语义上讲,这两个表达式具有相同的结果。
然而,BETWEEN是一个单一的谓词,而不是两个与AND组合的比较谓词。根据您的RDBMS提供的优化器,单个谓词可能比两个谓词更容易优化。
尽管我希望大多数现代RDBMS实现应该以相同的方式优化这两个表达式。

-1

我最好使用第二个,因为你总是知道它是 <= 还是 <


如果你熟练掌握SQL,你就知道BETWEEN的作用。否则,你只是在SQL中胡乱尝试 - 最好找一个数据库开发人员为你编写SQL! - Mr. Boy
1
我应该解雇现在的程序员吗?还是可以让他使用他理解的语法,而不是找一个新人来完成这项工作? - Dani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接