【发布时间】:2018-02-14 08:05:47
【问题描述】:
我有一个存储datetime 列的表,该列已编入索引。我正在尝试找到一种方法来仅比较月份和日期(完全忽略年份)。
为了记录,我想说我已经在使用MONTH() 和DAY()。但是我遇到了一个问题,即我当前的实现使用 Index Scan 而不是 Index Seek,因为在这两个函数中直接使用该列来获取月份和日期。
可以有 2 种类型的参考进行比较:固定的给定日期和今天(GETDATE())。日期将根据时区进行转换,然后提取其月份和日期,例如
DECLARE @monthValue DATETIME = MONTH(@ConvertDateTimeFromServer_TimeZone);
DECLARE @dayValue DATETIME = DAY(@ConvertDateTimeFromServer_TimeZone);
还有一点是该列存储了不同年份的日期时间,例如
1989-06-21 00:00:00.000
1965-10-04 00:00:00.000
1958-09-15 00:00:00.000
1965-10-08 00:00:00.000
1942-01-30 00:00:00.000
现在问题来了。如何创建 SARGable 查询以获取表中与给定月份和日期匹配的行,而不考虑年份,但也不涉及任何函数中的列?网络上的现有示例使用年份和/或日期范围,这对我来说根本没有帮助。
示例查询:
Select t0.pk_id
From dob t0 WITH(NOLOCK)
WHERE ((MONTH(t0.date_of_birth) = @monthValue AND DAY(t0.date_of_birth) = @dayValue))
我也尝试过DATEDIFF() 和DATEADD(),但它们都以索引扫描结束。
【问题讨论】:
-
您能否在存储“标准化”日期的表中添加一个计算列(这样它与您当前的列相同,但所有日期都在 2000 年)?
-
@Damien_The_Unbeliever 这是唯一能想到的选项,对您选择闰年有好处。
-
@Damien_The_Unbeliever 由于生产表的大小(大约 2000 万行)并且它也是用户生成的表,这样做是不可行的。
-
好吧,不幸的是,
datetime(或 datetime2)是自过去某个固定日期以来的间隔计数。假设是自 1900 年以来的日子(datetime的整数部分)。 42778 和 43143 代表两年中的同一个月和同一天,但无法索引此数据以进行可以知道的查询(闰日也确实搞砸了) -
您可以在上面使用Calendar Table 和
JOIN。确保您的日历具有月份编号和日期编号列,并且包含WHERE CT.MonthNum = @MonthValue AND CT.DayNum = @DayValue的查询是完全可搜索的。 (CT是日历表)。
标签: sql sql-server datetime query-performance