SQL Server BETWEEN 不够高效

4
我记得在某个地方听到或读到过,说到:
SELECT * from TABLE where date >= '2009-01-01' AND date <= '2009-12-31'

比...更高效
SELECT * from TABLE where date BETWEEN '2009-01-01' AND '2009-12-31'

日期列是DATETIME类型,并且具有相同的索引。这样正确吗?

1个回答

12

不,这不正确。

两种语法完全相同。

BETWEEN只是一种语法糖,是>= … AND <= …的简写方式。

对于所有主要系统(OracleMySQLPostgreSQL),这也是适用的,而不仅仅是适用于SQL Server

但是,如果你想检查日期是否在当前年份内,你应该使用这种语法:

date >= '2009-01-01' AND date < '2010-01-01'

注意,最后一个条件是严格的。

这与BETWEEN语句的语义不同,而且这是查询当前年份的首选方式(而非YEAR(date) = 2009,因为它不可搜索)。

您无法将此条件重写为BETWEEN,因为最后一个不等式是严格的,而BETWEEN条件包括范围边界。

需要使用严格条件,因为与整数不同,DATETIME不是良序的,也就是说,您不能确定“2009年可能的最后日期时间值”(当然这并不是特定于实现的)。


1
回答这些问题最简单的方法是查看两个语句的执行计划。您可能会发现计划完全相同,成本也完全相同。 - Joel Mansford
一个 SQL Server 2012 数据库中,DATE_TIME between '01/01/2013' and '01/01/14' 的语法等价于 DATE_TIME >= '01/01/2013' and DATE_TIME < '01/01/14'。两者都是可搜索的。 - craig
@craig:你是不是在第一个表达式中想要写成 CAST(DATE_TIME AS DATE) BETWEEN '01/01/2013' and '01/01/14' - Quassnoi
@Quassnoi:不,我想用日期/时间值来记录行为。但是,CAST(DATE_TIME AS DATE) BETWEEN '01/01/2013' AND '12/31/2013'在功能上等同于(具有相同的结果)DATE_TIME between '01/01/2013' and '01/01/14'——两者的成本相同。话虽如此,与非转换语法相比,CAST()操作有更多的操作(例如Compute ScalarMerge Interval)。 - craig
@craig:如果我们讨论datetime类型,那么between '01/01/2013' and '01/01/14'DATE_TIME >= '01/01/2013' and DATE_TIME < '01/01/14'在语法上不等价:第一个匹配的是2014-01-01 00:00:00.000,第二个则不是。而CAST操作没有任何额外的操作:它只是被优化器重写成了你的第二个表达式。 - Quassnoi
@Quassnoi:你说得对——我的数据中没有包含01/01/14 00:00:00.000这个值。SQL Fiddle可供验证。 - craig

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