2011-09-25 55 views
3

我試圖通過使用SQL Server Express 2008中的函數來提高查詢可讀性。 下面是我正在嘗試執行的一個示例。使用函數改進SQL查詢

我有一個表,我們存儲最大溫度每一天的時間閱讀,然後我想選擇所有天凡8-10AM之間的最高溫度比之間的最高溫度更大12-2PM

因此,這裏是如何像:

DECLARE @TableA TABLE ([Date] DATE, [Time] TIME(0), HighTemp DECIMAL(6,2)); 

INSERT @TableA VALUES 
('2011-09-10','08:00:00',38.15), 
('2011-09-10','09:00:00',38.32), 
('2011-09-10','10:00:00',38.17), 
('2011-09-10','11:00:00',38.10), 
('2011-09-10','12:00:00',38.05), 
('2011-09-10','13:00:00',38.15), 
('2011-09-10','14:00:00',38.30), 

('2011-09-11','08:00:00',38.12), 
('2011-09-11','09:00:00',38.09), 
('2011-09-11','10:00:00',38.07), 
('2011-09-11','11:00:00',38.15), 
('2011-09-11','12:00:00',38.13), 
('2011-09-11','13:00:00',38.11), 
('2011-09-11','14:00:00',38.10), 

('2011-09-12','08:00:00',38.30), 
('2011-09-12','09:00:00',38.33), 
('2011-09-12','10:00:00',38.35), 
('2011-09-12','11:00:00',38.30), 
('2011-09-12','12:00:00',38.25), 
('2011-09-12','13:00:00',38.23), 
('2011-09-12','14:00:00',38.20) 

select distinct [DATE] from @TableA maintbl 
where 
-- Select the high temp between 08:00:00-10:00:00 
(select MAX(HighTemp) from @TableA tmptbl where tmptbl.Time >= '08:00:00' and tmptbl.Time <= '10:00:00' and maintbl.Date = tmptbl.Date) 
> 
-- Select the high between 12:00:00-14:00:00 
(select MAX(HighTemp) from @TableA tmptbl where tmptbl.Time >= '12:00:00' and tmptbl.Time <= '14:00:00' and maintbl.Date = tmptbl.Date) 

查詢運行良好(快)和上面的查詢結果應該是: 2011-09-10 2011-09-12

現在,我試圖簡化查詢Ÿ通過使用檢索某一天和時間段的最大tempreture的功能,所以查詢更容易閱讀,就像這樣:

select distinct [DATE] from @TableA maintbl 
where GetPeriodHigh(maintbl.Date, '08:00:00', '10:00:00') > GetPeriodHigh(maintbl.Date, '12:00:00', '14:00:00') 

而且功能就像這樣:

CREATE FUNCTION [dbo].[GetPeriodHigh] 
(
    @Date date, 
    @From time, 
    @To time 
) 
RETURNS decimal(6,2) 
AS 
BEGIN 

    declare @res decimal(6,2) 

    select @res = MAX(high) from MyTable 
    where Time >= @from and Time <= @to and Date = @Date 

    return @res 
END 

問題是運行查詢使用該函數需要LONG時間,實際上我從來沒有看到它完成,看起來像是在某種無限循環...

任何想法,爲什麼是這樣的,而且有什麼我可以爲了簡化我的查詢嗎?

Thx。

+0

你有在桌子上有什麼指標,多少次測量,你每天? –

回答

5

做數據訪問的標量函數通常很糟糕,最好避免。它們不會被優化器擴展出來,並且基本上強制函數查詢作爲嵌套循環連接的內部,而不管其是否適合。

使事情變得更糟糕,您可能沒有正確的索引來評估函數內的Time >= @from and Time <= @to and Date = @Date謂詞,這意味着對於外部查詢中的每一行,您將通過函數調用強制實施2個表掃描。

缺乏指標也是在源例子的情況下,它可以與在線版本,查詢優化器能夠有效地改寫這個兩個MAX/GROUP BY查詢不同WHERE條款中可以看出然後合併連接的結果一起。當邏輯是標量UDF時,目前沒有考慮這種轉換。

Plan

你可以嘗試另一種方法是

SELECT [Date] 
FROM @TableA 
WHERE Time BETWEEN '08:00:00' AND '10:00:00' 
     OR Time BETWEEN '12:00:00' AND '14:00:00' 
GROUP BY [Date] 
HAVING MAX(CASE 
       WHEN Time BETWEEN '08:00:00' AND '10:00:00' THEN HighTemp END) > 
     MAX(CASE 
       WHEN Time BETWEEN '12:00:00' AND '14:00:00' THEN HighTemp END)