SQL: BEWEEN vs < = and > =

在 SQLServer2000和2005中:

  • 这两个 WHERE条款有什么区别?
  • 在哪些情况下我应该使用哪一个?

问题一:

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 最初丢失,因此查询语法错误)

208309 次浏览

它们是相同的: BETWEEN是问题中包含两个值(EventDate >= '10/15/2009' and EventDate <= '10/19/2009')的较长语法的简写。

如果 BETWEEN不起作用,因为其中一个或两个值都不应该包含,那么可以使用另一种较长的语法。

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

(在第二种情况下注意 <而不是 <=。)

通常情况下,没有区别-在所有 RDBMS 平台上都不支持 BETWEEN关键字,但是如果支持,那么这两个查询应该是相同的。

因为它们是完全相同的,所以在速度或其他方面没有区别——使用对你来说更自然的那个。

我认为唯一的区别是每个查询上的语法 Sugar 的数量。与第二个查询完全相同的说法只是一种巧妙的方式。

可能有一些 RDBMS 特定的差异,我不知道,但我真的不这样认为。

他们是一样的。

需要注意的一点是,如果你使用的是 DATETIME,结束日期的匹配将是一天的开始:

<= 20/10/2009

不同于:

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

(它的 匹配对 <= 20/10/2009 00:00:00.000)

从逻辑上讲,这两者没有任何区别。 在性能方面——通常在大多数 DBMS 上——没有任何区别。

正如@marc _ s、@Cloud 等人提到的,它们对于封闭范围基本上是相同的。

但是,任何分数时间值可能导致问题与一个封闭的范围(大于等于和 小于或等于) ,而不是半开放的范围(大于等于和 低于)与结束值 之后的最后一个可能的瞬间。

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

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

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

我对 BETWEEN有点偏好,因为它能立即让读者明白 您正在检查一个字段以确定范围。如果您的表中有类似的字段名,这种情况尤其明显。

如果,比方说,我们的表同时有一个 transactiondate和一个 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,当然,这将是一个语法错误,并迅速修复。

虽然 BETWEEN易于阅读和维护,但我很少建议使用它,因为它是一个封闭的间隔,正如前面提到的,这可能是一个日期问题-即使没有时间组件。

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

此外,另一个问题是,需要在 命令正确(即 BETWEEN low AND high)中指定下限和上限。

有无限的逻辑等价语句,但我会考虑三(左右)。

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

A > = MinBound AND A < = MaxBound

案例2: 句法糖(评价顺序不由作者选择)

在最小和最大之间

案例3: 按受教育顺序进行的两次比较(在写入时选择评估顺序)

A > = MinBound AND A < = MaxBound

或者

A < = MaxBound AND A > = MinBound

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

然而,案例3可以极大地提高执行时间。具体来说,如果您正在处理一个大型数据集,并且碰巧有一些关于 A是更可能大于 MaxBound还是小于 迷你绑定的启发性知识,那么您可以通过使用 Case 3并相应地排序比较来显著地提高执行时间。

我拥有的一个用例是查询一个大型的历史数据集,其中包含在特定时间间隔内的非索引日期记录。在编写查询时,我将很好地了解在指定的时间间隔之前或之后是否存在更多的数据,并且可以相应地对比较进行排序。根据数据集的大小、查询的复杂性以及第一次比较过滤的记录数量,我将执行时间减少了一半。

在这个场景中,col BETWEEN ... AND ...col <= ... and col >= ...是等价的。


SQL 标准也定义了 T461谓词间对称:

 <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 < > 小提琴演奏