我需要知道(并标记)子查询中的特定事件是否在下午3:30之后发生(无论日期如何)。
对于我的设置,我无法通过试用来确定哪种效率更高(它们回来得太快),并且执行计划没有帮助。
第二个(#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以上版本
答案 0 :(得分:2)
就个人而言,如果可以的话,我实际上会向表中添加一个计算列。如果使用该路由,CONVERT
/ CAST
到time
数据类型绝对是必经之路,但是如果您可以添加一个持久化的计算列,则可以对该列建立索引或添加它到您现有的表中,并且如果您需要在WHERE
中查询此数据,则保持SARGability(我知道这里的示例是一个临时表,但我怀疑实际情况是这样):
ALTER TABLE #jccTestData ADD ProcessTime AS CONVERT(time,ProcessDate) PERSISTED;
然后,您可以查询新列:
SELECT [ProcessDate],
CASE WHEN ProcessTime >= '03:30' THEN 'After 3:30 PM' END AS [After 3:30?]
FROM #jccTestData
ORDER BY [ProcessDate];
此外,避免对ORDER BY
中的列使用序数,最好使用列的实际名称。
旁注,您无需具有用于强制转换/转换为date
数据类型的列。 CONVERT(date,ProcessDate)
和CAST(ProcessDate AS date)
均可保存。
答案 1 :(得分:2)
由于您在询问效率,因此我对超过一百万条真实记录进行了一些基准测试。下面的最后一种方法(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
答案 2 :(得分:0)
如果您确实不更改apply
结构,我将使用第三个选项DB
:
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];