Sql server 在一天中的特定时间之后-哪种方法更好?
我需要知道(并标记)子查询中的特定事件是否发生在下午3:30之后(无论日期)。Sql server 在一天中的特定时间之后-哪种方法更好?,sql-server,Sql Server,我需要知道(并标记)子查询中的特定事件是否发生在下午3:30之后(无论日期)。 在我的设置中,我无法通过试验确定哪一个更有效(他们回来得太快),执行计划也没有帮助 第二个(#2)对我来说似乎更有效,因为文本只需要强制转换一次(每行保留一个操作)。 然而,有时像这样的操作是骗人的,所以我希望有人能告诉我哪个更好 CREATE TABLE #jccTestData([ProcessDate] datetime); INSERT INTO #jccTestData ([ProcessDate]) VA
在我的设置中,我无法通过试验确定哪一个更有效(他们回来得太快),执行计划也没有帮助 第二个(#2)对我来说似乎更有效,因为文本只需要强制转换一次(每行保留一个操作)。
然而,有时像这样的操作是骗人的,所以我希望有人能告诉我哪个更好
CREATE TABLE #jccTestData([ProcessDate] datetime);
INSERT INTO #jccTestData ([ProcessDate])
VALUES
('2019-03-12 10:23:28.000') ,('2019-03-17 11:22:40.000'), ('2019-03-18 11:25:30.000')
,('2019-03-19 11:42:02.000') ,('2019-03-11 12:45:30.000') ,('2019-03-12 13:14:20.000')
,('2019-03-13 15:20:13.000') ,('2019-03-14 15:29:40.000') ,('2019-03-15 15:29:59.997')
,('2019-03-16 15:30:00.000') ,('2019-03-17 15:30:00.003') ,('2019-03-18 16:25:30.000')
,('2019-03-12 23:59:59.997') ,('2019-03-13 00:00:00.003') ,('2019-03-14 00:00:00.000')
,('2019-03-15 03:14:20.000') ,('2019-03-16 05:20:13.000')
SELECT
[ProcessDate]
, Case When datepart(HH, [ProcessDate]) > 15
OR (datepart(HH, [ProcessDate]) = 15 And datepart(n, [ProcessDate]) >= 30)
Then 'After 3:30 PM'
End As [After 3:30? #1]
, Case When cast([ProcessDate] As time) >= cast('15:30:00' As time)
Then 'After 3:30 PM'
End As [After 3:30? #2]
FROM #jccTestData
ORDER BY [ProcessDate]
DROP TABLE #jccTestData
第二个似乎也更易于维护
如果还有第三种选择,我也愿意接受。SQL Server 2012+我个人认为,如果可以的话,我实际上会向您的表中添加一个计算列<如果使用该路径,代码>转换/
转换
到时间数据类型无疑是一种方法,但是如果您可以添加一个持久化的计算列,那么您可以索引该列,或者将其添加到现有列中,如果您需要在WHERE
(我意识到这里的示例是一个临时表,但我怀疑实际情况是):
然后,您可以只查询该新列:
SELECT [ProcessDate],
CASE WHEN ProcessTime >= '03:30' THEN 'After 3:30 PM' END AS [After 3:30?]
FROM #jccTestData
ORDER BY [ProcessDate];
此外,请避免在“排序依据”中对列使用序号,最好使用列的实际名称
旁注,您不需要有一个列来转换数据类型。
CONVERT(date,ProcessDate)
和CAST(ProcessDate AS date)
都是可搜索的。如果您确实不更改DB
结构,我会使用第三个选项,即apply
:
SELECT d.[ProcessDate],
(CASE WHEN dd.ProcessTime >= '15:30' THEN 'After 3:30 PM' END) AS [After 3:30?]
FROM #jccTestData d CROSS APPLY
( VALUES (CONVERT(TIME, ProcessDate))
) dd (ProcessTime )
ORDER BY d.[ProcessDate];
因为你问的是效率,我对超过一百万条真实记录做了一些基准测试。下面的最后一个方法(CAST)报告了更多的CPU时间。所有时间都以毫秒为单位,因此你需要数百万条记录才能注意到任何差异
IIF((DATEPART(HH, dateStamp) * 60) + DATEPART(MINUTE, dateStamp) >= 930, 'After 3:30 PM', '')
IIF(DATEPART(HH, dateStamp) > 15 OR (DATEPART(HH, dateStamp) = 15 AND DATEPART(N, dateStamp) >= 30), 'After 3:30 PM', '')
IIF(CAST(dateStamp AS TIME) >= CAST('15:30:00' AS TIME), 'After 3:30 PM', '')
1) 平均CPU时间:477;平均运行时间:242
2) 平均CPU时间:469;平均运行时间:236
3) 平均CPU时间:808;平均运行时间:413差别不大。这是结果中的一列,因此索引在这里不是问题。但您不应该按顺序位置排序,如果您查询更改,可能会导致各种问题。@SeanLange True。我太草率了,即使使用测试代码,我也没有树立一个坏榜样。现在改变模式不是一个选项,但谢谢你提到它。我对你使用“SARG”(SARGability&SARGable)一词感到茫然。您能告诉/提醒我这代表什么吗?@J.ChrisCompton如果查询是可搜索的,则表示
WHERE
包含可搜索的参数,而不是可用于索引的参数。类似于WHERE CONVERT(time,ProcessDate)>'03:30'
的内容是不可搜索的,因为CONVERT
更改了列ProcessDate
的顺序,这意味着不能使用索引。即使如此,仅仅因为表达式不改变顺序,也不能使其成为可搜索的。“对于几百万行来说,几乎没有区别。”谢谢,这就涵盖了问题。有趣的是,强制转换比乘法更需要CPU。如果可以的话,我会给你另一个+1,用于转换为分钟,这是我自己应该想到的。当我试图减少其他意外事件时,CAST方法的性能差异超过25%,所以我更新了帖子。
IIF((DATEPART(HH, dateStamp) * 60) + DATEPART(MINUTE, dateStamp) >= 930, 'After 3:30 PM', '')
IIF(DATEPART(HH, dateStamp) > 15 OR (DATEPART(HH, dateStamp) = 15 AND DATEPART(N, dateStamp) >= 30), 'After 3:30 PM', '')
IIF(CAST(dateStamp AS TIME) >= CAST('15:30:00' AS TIME), 'After 3:30 PM', '')