SQL:与<=和> =之间


111

在SQL Server 2000和2005中:

  • 这两个WHERE子句有什么区别?
  • 我应该在哪种情况下使用哪一个?

查询1:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate BETWEEN '10/15/2009' AND '10/18/2009'

查询2:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate >='10/15/2009'
  AND EventDate <='10/18/2009'

(编辑:最初缺少第二个Eventdate,因此查询在语法上是错误的)



6
并非如此,datetime的处理方式略有不同,再加上SQL Server 2008的处理方式,并且Shyju在不询问答案与先前版本相同的情况下是无法确定的。
Irfy

Answers:


119

它们是相同的:BETWEEN是问题中较长语法的简写。

BETWEEN无法使用的地方使用其他更长的语法,例如

Select EventId,EventName from EventMaster
where EventDate >= '10/15/2009' and EventDate < '10/18/2009'

(请注意,<而不是<=处于第二状态。)


19
也许您应该强调指出第二个条件是“ <”。我花了一些时间才能发现差异。
zendar

21
我要补充一点,我强烈建议您不要使用BETWEEN,除非您正在处理DATE数据类型,或者以其他方式保证您的datetime值永远不会包含时间分量。对此保持一致将使您不太可能错误地使用BETWEEN而不是> =和<,并且在查询中获得了您原本不希望的一些数据,或者认为您将获得额外的一天数据,当您不是...
Aaron Bertrand

1
随着BETWEEN转换为条件语句,还会有第二个编译器步骤吗?我知道这有点花哨,但是会产生额外的开销吗?
詹姆斯·斯科特

1
@xmashallax,因为它们是?他们怎么不呢?
托尼·安德鲁斯

2
奇怪...我认为我对问题,答案的书写,注释以及我的代码现在显然有错误的事实感到困惑=)
xmashallax

37

他们是一样的。

要注意的一件事是,如果您在DATETIME上使用它,则结束日期的匹配将是一天的开始:

<= 20/10/2009

与以下内容不同:

<= 20/10/2009 23:59:59

(这对阵<= 20/10/2009 00:00:00.000


在这种情况下,您只需在“ 2009-10-20”和“ 2009-10-21”之间使用即可捕获一天
David Andrei Ned

4
@DavidAndreiNed也将匹配“ 2009-10-21 00:00:00.000”-可能不是您想要的。
汉斯·

2
您可能想在'2009-10-20 00:00:00'和'2009-10-20 23:59:59'之间输入字段,或者>>'2009-10-20 00:00:00'和字段<= “ 2009-10-20 23:59:59”可以肯定。
geilt

@geilt您的示例将丢失在当天的最后一秒内发生的所有事件……即:第二天的23:59:59至00:00:00之间。
赛斯花

00:00:00是第二天的开始,为什么我要使用> =和<=而不是>或<。但是,如果您要表示微秒并存储它们,那么您也希望同时使用最后一个和最后一个微秒。
geilt

14

尽管BETWEEN易于阅读和维护,但我很少建议使用它,因为它是一个封闭的时间间隔,并且如前所述,这可能是日期问题-即使没有时间成分也是如此。

例如,在处理月度数据时,通常比较日期是很常见的BETWEEN first AND last,但是在实践中,这通常更容易编写dt >= first AND dt < next-first(这也解决了时间部分的问题)-因为确定last通常比确定next-first(减去一天)长一个步骤。。

另外,另一个陷阱是确实需要以正确的顺序(即BETWEEN low AND high)指定下限和上限。


4

通常,没有区别- BETWEEN并非所有RDBMS平台都支持该关键字,但是如果支持,则两个查询应该相同。

由于它们是相同的,因此实际上在速度或其他任何方面都没有区别-使用对您来说更自然的选择。


4

如@ marc_s,@ Cloud等所述。它们在近距离范围内基本相同。

但是,任何小数时间值都可能导致闭合范围(大于或等于而小于或等于)的问题,而不是半开范围(大于等于或小于等于)的最终值出现问题。最后可能的瞬间。

因此,为了避免查询应重写为:

SELECT EventId, EventName
  FROM EventMaster
 WHERE (EventDate >= '2009-10-15' AND
        EventDate <  '2009-10-19')    /* <<<== 19th, not 18th */

由于BETWEEN半开间隔不起作用,因此我总是仔细检查使用它的任何日期/时间查询,因为它可能是错误的。


4

我有些偏爱,BETWEEN因为它使读者可以立即清楚地看到您正在检查一个字段的范围。如果表中具有相似的字段名称,则尤其如此。

如果说,如果我们的表同时具有a transactiondate和a transitiondate,则读取

transactiondate between ...

我立即知道测试的两端都针对这一领域。

如果我读

transactiondate>='2009-04-17' and transactiondate<='2009-04-22'

我必须花一点时间来确保两个字段相同。

另外,随着查询的编辑,时间的推移,草率的程序员可能会将这两个字段分开。我已经看到很多查询,例如

where transactiondate>='2009-04-17'
  and salestype='A'
  and customernumber=customer.idnumber
  and transactiondate<='2009-04-22'

如果他们尝试使用BETWEEN,当然会出现语法错误,并会立即修复。


3

我认为唯一的区别是每个查询的语法糖量。BETWEEN是一种与第二种查询完全相同的巧妙表达方式。

我可能不知道某些RDBMS特定的差异,但我并不这么认为。


2

逻辑上根本没有区别。在性能方面,通常,在大多数DBMS上,根本没有区别。



1

免责声明:以下内容仅是轶事,直接来自我的个人经验。如果我愿意,任何愿意进行更严格的经验分析的人都可以对其进行投票。我也知道SQL是一种声明性语言,您不必在编写代码时考虑如何处理您的代码,但是,因为我很珍惜我的时间,所以我愿意这样做。

在逻辑上有无限等价的语句,但我将考虑三个。

情况1:标准顺序中的两个比较(评估顺序固定)

A> = MinBound和A <= MaxBound

情况2:语法糖(作者未选择评估顺序)

MinBound和MaxBound之间

情况3:按教育顺序进行两次比较(在写入时选择评估顺序)

A> = MinBound和A <= MaxBound

要么

A <= MaxBound和A> = MinBound

以我的经验,案例1和案例2在性能上没有任何一致或显着的差异,因为它们对数据集一无所知。

但是,情况3可以大大缩短执行时间。具体来说,如果您使用的是大型数据集,并且碰巧具有有关A是否更有可能大于MaxBound或小于MinBound的启发式知识,则可以通过使用案例3并排序比较来显着缩短执行时间相应地。

我有一个用例是查询具有未索引日期的大型历史数据集以查找特定时间间隔内的记录。编写查询时,我会很好地知道在指定间隔之前还是之后,是否存在更多数据,并可以据此对比较进行排序。根据数据集的大小,查询的复杂性以及第一次比较过滤后的记录数量,执行时间最多减少了一半。


嗯什么?情况3与情况1和情况2的逻辑不同。如果您想查看是否A大于,则只需检查是否A大于MaxBound。您的帖子需要一些调整。
mickmackusa

看起来我在等式运算符上打了错字。接得好。
LanchPad

0

在这种情况下col BETWEEN ... AND ...col <= ... and col >= ...是等价的。


SQL标准还定义了T461对称BETWEEN谓词

 <between predicate part 2> ::=
 [ NOT ] BETWEEN [ ASYMMETRIC | SYMMETRIC ]
 <row value predicand> AND <row value predicand>

Transact-SQL不支持此功能。

BETWEEN要求对值进行排序。例如:

SELECT 1 WHERE 3 BETWEEN 10 AND 1
-- no rows

<=>

SELECT 1 WHERE 3 >= 10 AND 3 <= 1
-- no rows

另一方面:

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 1 AND 10;
-- 1

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 10 AND 1
-- 1

它完全正常工作,BETWEEN但是对比较值进行了排序。

db <> fiddle演示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.