DATEDIFF() 或 BETWEEN 用于 SQL 查询中的日期范围
Posted
技术标签:
【中文标题】DATEDIFF() 或 BETWEEN 用于 SQL 查询中的日期范围【英文标题】:DATEDIFF() or BETWEEN for Date Ranges in SQL Queries 【发布时间】:2013-01-04 08:48:58 【问题描述】:我最近被告知在 SQL 中使用BETWEEN
方法有些不可靠,因此我应该使用DATEDIFF()
。但是,另一位程序员告诉我情况并非如此,只要日期格式正确,BETWEEN
方法在所有情况下都能出色地工作。
请有人通过说明哪种方法更好以及为什么来解决这场争论?
目前我的日期范围 SQL 如下所示:
DATEDIFF(d,'01-Jan-1970',SIH.[Something_Date]) >= 0 AND DATEDIFF(d,'01-Jan-2013',SIH.[Something_Date]) <= 0
但是,如果我能确定它是可靠的,我宁愿这样写:
SIH.[Something_Date] BETWEEN '01-Jan-1970' AND '01-Jan-2013'
在这种特殊情况下,我使用的是 MsSQL,但是,我已经标记了 MySQL,因为我想知道这是否也适用于此
【问题讨论】:
“SQL 中的 BETWEEN 方法有些不可靠”——什么意思? 在这种情况下,您应该选择两者之间,因为它会在扫描时考虑索引,但在 DATEDIFF 中不考虑索引 @MitchWheat 这就是我被告知的,他没有说明为什么它不可靠,他只是说我不应该使用它 也许他们试图引用列有时间部分的事实?这与“不可靠”非常不同 如果不是不可靠的,它至少被一些人认为是邪恶的。 What do BETWEEN and the devil have in common? 【参考方案1】:您的两个查询不等价。 datediff
版本将包括来自01-Jan-2013
的所有值,而与时间无关,而介于两者之间的版本将仅包括01-Jan-2013
上时间为00:00:00
的行。
如果您检查范围并且不对列进行任何计算,则您的查询将能够使用Something_Date
上的索引,同时包括来自01-Jan-2013
的所有值,无论时间部分如何.
where
SIH.[Something_Date] >= '19700101' and
SIH.[Something_Date] < '20130102'
【讨论】:
很困惑,你是说如果一个字段指定的时间不是 00:00:00 那么BETWEEN
会找不到它吗?
@BenCarey 是的,这就是我的意思。当开发人员发现这一点时,他们通常会在“第二天”之间做一个间隔,而不是有副作用,即他们包含从第二天开始的带有时间 00:00:00
的行。当他们弄清楚这一点时,他们会写中间以使用20130101 23:59:59
,并错过了最后一秒。当他们发现这一点时,他们尝试20130101 23:59:59.999
只是为了发现datetime
值的精度为3 ms,因此它向上舍入到20130102 00:00:00
。到那时,即使20130101 23:59:59.997
确实有效,他们也希望停止使用 between,至少对于 datetime
。
太棒了,这就是我被指示不要使用它的原因。非常感谢:-) +1【参考方案2】:
避免 BETWEEN 的原因是,如果您的日期值可以包含时间组件,则无法正确使用它。如果包括时间,则与上限的比较必须使用严格小于比较,排除 BETWEEN。
另一方面,如果您知道日期值从不包含时间组件,或者如果您有一种方便的方法可以删除时间组件,那么我更喜欢使用 BETWEEN,因为它看起来更具可读性。
在 Oracle SQL 中,我可以使用 TRUNC 函数来删除时间部分(它也可以截断为 'MONTH' 或 'YEAR')。
所以我可以写:
where TRUNC(date_col) between '01-JAN-2021' and '31-DEC-2021'
并确保测试不会错过 31 日也有时间成分的日期。
我的印象是,TRUNC
(和ROUND
)的这种用法可能是 Oracle 独有的。我不知道 mysql 或 T-SQL 中是否有等价物。 (我似乎记得必须使用 datediff
技巧来完成 TRUNC 的工作。
如果没有TRUNC
(或等效项),您必须使用:
where '01-JAN-2021' <= date_col and date_col < '01-JAN-2022'
注意与上限的比较必须严格小于。
这更短,可读性更强,可能更高效,并且保证可以工作。
但我还是更喜欢使用TRUNC
和BETWEEN
,因为逻辑更清晰。 (在我做对之前,我以两种不同的方式搞砸了第二个示例)。
我怀疑效率是否存在很大差异,即使在大多数情况下,这也可能不是问题。我认为可读性比效率更重要(大多数时候)。
当然,正确性胜过一切。所以如果你没有方便的方法来移除时间分量或者必须包含时间分量,那么你就不能使用BETWEEN
来准确测试datetime
的值。
【讨论】:
以上是关于DATEDIFF() 或 BETWEEN 用于 SQL 查询中的日期范围的主要内容,如果未能解决你的问题,请参考以下文章