5

我最近被告知BETWEEN在 SQL 中使用该方法有些不可靠,因此我应该使用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,因为我想知道这是否也适用于此

4

2 回答 2

6

您的两个查询不等价。该datediff版本将包括所有值,01-Jan-2013而与时间无关,而介于版本之间的版本将仅包括01-Jan-2013time 所在的行00:00:00

如果您检查范围并且不对列进行任何计算,则您的查询将能够使用索引Something_Date并同时包含来自01-Jan-2013任何时间部分的所有值。

where
  SIH.[Something_Date] >= '19700101' and
  SIH.[Something_Date] < '20130102'
于 2013-01-04T08:59:26.723 回答
0

避免 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'

请注意,与上限的比较必须严格小于。

这更短,可读性更强,可能更有效,并且可以保证工作。

但我还是更喜欢使用TRUNCandBETWEEN因为逻辑更清晰。(在我做对之前,我以两种不同的方式搞砸了第二个例子)。

我怀疑效率是否存在很大差异,即使在大多数情况下,这也可能不是问题。我认为可读性比效率更重要(大多数时候)。

但当然,正确性胜过一切。因此,如果您没有方便的方法来删除时间分量或必须包含时间分量,那么您就无法BETWEEN准确地测试datetime值。

于 2022-01-28T05:31:30.783 回答