2011-12-19 105 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