Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.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 为什么在DateAdd中使用硬编码分钟比使用字段值快?_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql server 为什么在DateAdd中使用硬编码分钟比使用字段值快?

Sql server 为什么在DateAdd中使用硬编码分钟比使用字段值快?,sql-server,sql-server-2008,Sql Server,Sql Server 2008,处理SQL问题时,我不是SQL专家,所以需要一些指导 给出下面的SQL语句,请注意,第一个语句在DateAdd函数中使用硬编码值-360,而第二个语句使用存在于每个记录上的字段值偏移量,该记录的值为-360或-300,具体取决于DST时间 运行第一个查询的速度非常快,而第二个查询需要大约40秒 有人能告诉我第二个记录执行时间长的区别是什么吗?因为我必须使用该记录的值,而不是硬编码它,我如何加快查询速度 查询1快速: SELECT 0 AS 'TempIndex', COUNT(*) AS 'To

处理SQL问题时,我不是SQL专家,所以需要一些指导

给出下面的SQL语句,请注意,第一个语句在DateAdd函数中使用硬编码值-360,而第二个语句使用存在于每个记录上的字段值偏移量,该记录的值为-360或-300,具体取决于DST时间

运行第一个查询的速度非常快,而第二个查询需要大约40秒

有人能告诉我第二个记录执行时间长的区别是什么吗?因为我必须使用该记录的值,而不是硬编码它,我如何加快查询速度

查询1快速:

SELECT 0 AS 'TempIndex', COUNT(*) AS 'TotalLY'
FROM CLOGS15 h 
WHERE h.EVTYPE = 1 
AND DateAdd(minute, -360, h.EVDATE) BETWEEN '2015-01-01 00:00:00.000' AND '2015-01-24 00:00:00.000'
查询2慢:

SELECT 0 AS 'TempIndex', COUNT(*) AS 'TotalLY'
FROM CLOGS15 h 
WHERE h.EVTYPE = 1 
AND DateAdd(minute, OFFSET, h.EVDATE) BETWEEN '2015-01-01 00:00:00.000' AND '2015-01-24 00:00:00.000'

我只能想象问题在于索引用户的可搜索性。然而,我认为dateadd会阻止使用索引。但是,如果您想解决此问题,可能这将起作用:

SELECT 0 AS TempIndex, COUNT(*) AS TotalLY
FROM CLOGS15 h 
WHERE h.EVTYPE = 1 AND offset = 360 AND
      DateAdd(minute, -360, h.EVDATE) BETWEEN '2015-01-01' AND '2015-01-24'
UNION ALL
SELECT 0 AS TempIndex, COUNT(*) AS TotalLY
FROM CLOGS15 h 
WHERE h.EVTYPE = 1 AND offset = 300 AND
      DateAdd(minute, -300, h.EVDATE) BETWEEN '2015-01-01' AND '2015-01-24';
编辑:

哦,上面返回两行,您需要一行。因此,使用子查询:

SELECT TempIndex, SUM(TotalLY) as TotalLY
FROM (SELECT 0 AS TempIndex, COUNT(*) AS TotalLY
      FROM CLOGS15 h 
      WHERE h.EVTYPE = 1 AND offset = 360 AND
            DateAdd(minute, -360, h.EVDATE) BETWEEN '2015-01-01' AND '2015-01-24'
      UNION ALL
      SELECT 0 AS TempIndex, COUNT(*) AS TotalLY
      FROM CLOGS15 h 
      WHERE h.EVTYPE = 1 AND offset = 300 AND
            DateAdd(minute, -300, h.EVDATE) BETWEEN '2015-01-01' AND '2015-01-24'
    ) h
GROUP BY TempIndex;

在您的例子中,我认为快速查询和慢速查询的区别在于索引的使用

在快速查询中,SQL Server可能正在重写DATEADD以启用EVDATE上的索引使用。当您添加日期和常量并检查它是否介于到常量日期之间时,它可能会将DATEADD从介于之间之前的左侧移动到介于之间之后的右侧,从而反转DATEADD中常量的信号

你的原件是:

DateAdd(minute, -360, h.EVDATE) 
  BETWEEN '2015-01-01 00:00:00.000' 
      AND '2015-01-24 00:00:00.000'
它可能转向:

h.EVDATE 
  BETWEEN DateAdd(minute, 360, '2015-01-01 00:00:00.000') 
      AND DateAdd(minute, 360, '2015-01-24 00:00:00.000')
这与原始筛选器相同,但支持索引使用和DATEADD的处理,因为只需要处理两个日期,而不需要处理表中的所有日期

在慢速查询中,由于DATEADD使用的是可变偏移量,SQL Server无法应用上述相同的规则,因此它使用DATEADD处理表中的所有日期,这非常慢

我认为您应该尝试快速查询之类的过滤器,可能是这样的:

SELECT 0 AS 'TempIndex', COUNT(*) AS 'TotalLY'
FROM CLOGS15 h 
WHERE 1=1 
  AND h.EVTYPE = 1 
  AND 
  (0=1
    OR
    (1=1
      AND OFFSET = -360
      AND h.EVDATE >= DateAdd(minute, 360, '2015-01-01 00:00:00.000') 
      AND h.EVDATE <= DateAdd(minute, 360, '2015-01-24 00:00:00.000')
    )
    OR
    (1=1
      AND OFFSET = -300
      AND h.EVDATE >= DateAdd(minute, 300, '2015-01-01 00:00:00.000') 
      AND h.EVDATE <= DateAdd(minute, 300, '2015-01-24 00:00:00.000')
    )
  )

如果能查询一个分别包含EVTYPE、OFFSET和EVDATE列的索引,那就太好了。

对SQL进行了一个小的编辑,在WHERE子句中360和300前面添加了一个-现在执行。我得到了正确的答案太棒了!,但是它现在输出第二行,每个值都是0。有并没有办法让它在我知道的第二个字段中只输出一条总计为1的记录,但这很有意义,因为它使我的PHP脚本编写更容易。请理解原因的解释,但上面的查询返回的总计不正确。@SourceMatters您能再试一次吗,因为我忘记了偏移量计算中的信号…仍然不足80-@Gordon的示例给出了正确的值,并根据SMMS在不到1秒的时间内执行。