TSQL在Where子句中使用Time

时间:2011-12-19 17:25:14

标签: sql-server-2008 tsql

我有一个温度测量值存储在一个表格中,每个测量值都有实际的日期/时间但从逻辑上来说,测量日从中午到中午(而不是午夜 - 模式)运行。 例如,在09/18/2011 09:00:00完成的措施将属于09/18/2011“计量日”但是 在09/18/2011 13:00:00完成的测量已经属于09/19/2011“测量日”。

所以现在我想做一些统计查询,比如每个“测量日”中09-11之间的平均温度,这可以通过以下方式完成:

-- Select the AVG temp between 09-11    
select MeasureDate, AVG(Temp) from @d
where Time between '09:00:00' and '11:00:00'
Group by MeasureDate

但是如果我希望平均温度在23:00-01:00之间,我必须使用不同的查询(时间“介于”之间不工作):

-- Select the AVG temp between 23:00-01:00
select MeasureDate, AVG(Temp) from @d
where (Time>='23:00:00' or Time<='01:00:00')
Group by MeasureDate

是否有一种简单的方法可以使用相同的查询来支持这两种方案? 理想情况下,我希望有一个函数将@ from / @作为参数,并将结果作为表返回。

以下是您可以运行的完整示例。 THX!

DECLARE @d TABLE ([Date] DATE, [Time] TIME(0), Temp DECIMAL(6,3), [MeasureDate] DATE); 

INSERT @d VALUES 
('2011-09-18','09:00:00',38.15, '2011-09-18'),
('2011-09-18','10:00:00',38.20, '2011-09-18'),
('2011-09-18','11:00:00',38.22, '2011-09-18'),
('2011-09-18','23:00:00',38.22, '2011-09-19'), -- Note the difference here between Date and     MeasureDate
('2011-09-19','00:00:00',38.17, '2011-09-19'),
('2011-09-19','01:00:00',38.32, '2011-09-19'),

('2011-09-19','09:00:00',39.15, '2011-09-19'),
('2011-09-19','10:00:00',39.20, '2011-09-19'),
('2011-09-19','11:00:00',39.22, '2011-09-19'),
('2011-09-19','23:00:00',39.22, '2011-09-20'), -- Note the difference here between Date and     MeasureDate
('2011-09-20','00:00:00',39.17, '2011-09-20'),
('2011-09-20','01:00:00',39.32, '2011-09-20');

-- Select the AVG temp between 09-11    
select MeasureDate, AVG(Temp) from @d
where Time between '09:00:00' and '11:00:00'
Group by MeasureDate

-- Select the AVG temp between 23:00-01:00
select MeasureDate, AVG(Temp) from @d
where (Time>='23:00:00' or Time<='01:00:00')
Group by MeasureDate

1 个答案:

答案 0 :(得分:0)

简短(且效率低下)答案:预处理您的Time值(当然还有您的比较值); “TIME”值会滚动,因此您无需担心添加或删除天数:

SELECT MeasureDate, AVG(Temp) 
FROM @d
WHERE DateAdd(Hour, 12, [Time]) >= DateAdd(Hour, 12, Convert(Time, '09:00:00'))
    AND DateAdd(Hour, 12, [Time]) < DateAdd(Hour, 12, Convert(Time, '11:00:00'))
GROUP BY MeasureDate

这为您提供了一致的查询,但当然不是特别漂亮。 (您可以在其他地方预处理时间,无需在SQL中执行此操作。)

在性能方面(如果你曾经或者曾经需要Time / MeasureTime的索引),更“正确”的方法是存储预处理的“MeasureTime”并直接进行比较:

SELECT MeasureDate, AVG(Temp) 
FROM @d
WHERE MeasureTime >= DateAdd(Hour, 12, Convert(Time, '09:00:00'))
    AND MeasureTime < DateAdd(Hour, 12, Convert(Time, '11:00:00'))
GROUP BY MeasureDate

“MeasureTime”可以通过客户端代码维护,也可以作为索引计算列维护,或者通过触发器维护 - 有很多方法可以帮助您进一步加快痛苦!

请注意,在这些示例中,我使用的是大于和小于版本而不是BETWEEN,因为根据我的经验,在日期/时间使用BETWEEN始终是错误的。