Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在一天中的特定时间之后-哪种方法更好?_Sql Server - Fatal编程技术网

Sql server 在一天中的特定时间之后-哪种方法更好?

Sql server 在一天中的特定时间之后-哪种方法更好?,sql-server,Sql Server,我需要知道(并标记)子查询中的特定事件是否发生在下午3:30之后(无论日期)。 在我的设置中,我无法通过试验确定哪一个更有效(他们回来得太快),执行计划也没有帮助 第二个(#2)对我来说似乎更有效,因为文本只需要强制转换一次(每行保留一个操作)。 然而,有时像这样的操作是骗人的,所以我希望有人能告诉我哪个更好 CREATE TABLE #jccTestData([ProcessDate] datetime); INSERT INTO #jccTestData ([ProcessDate]) VA

我需要知道(并标记)子查询中的特定事件是否发生在下午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+

我个人认为,如果可以的话,我实际上会向您的表中添加一个计算列<如果使用该路径,代码>转换/
转换
到时间数据类型无疑是一种方法,但是如果您可以添加一个持久化的计算列,那么您可以索引该列,或者将其添加到现有列中,如果您需要在
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', '')