2011-12-19 65 views
0

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

所以现在我想要做一些统计查询,就像在每个“测量日” 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 

有一个简单的办法有相同的查询,以支持两个场景? 理想情况下,我想有一个函数,它将@从/ @作为参数,并将结果作为表返回。

下面是一个可以运行的完整示例。 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

这实际上并不是您的问题的答案,但为避免重复计算报告中的值,您应该不会使用BETWEEN,而是使用不等式:'WHERE Time> = '09:00:00'AND时间<'11:00:00'' – Tao 2011-12-19 17:29:41

回答

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中完成)。

更“正确”的方法,在性能方面(如果您有或曾经需要时间/ 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总是错误的。

+0

Thx,由于某种原因,我得到了这个错误: – YWsecond 2011-12-19 22:56:09

+0

Thx,由于某种原因我得到这个错误: “数据类型时间和日期时间在大于或等于运算符不兼容“。 This worked: DateAdd(Hour,12,Time)> = CONVERT(Time,DateAdd(Hour,12,'09:00:00')) – YWsecond 2011-12-19 22:57:27