2009-08-17 85 views
2

我正在嘗試優化一些SQL代碼。在代碼中是一個運行相當昂貴的視圖。爲了這個問題,我們稱之爲ExpensiveView。在視圖的頂部有一個查詢通過兩個子查詢將視圖連接到自身。爲sql查詢優化幫助

例如:

select v1.varCharCol1, v1.intCol, v2.intCol from (
    select someId, varCharCol1, intCol from ExpensiveView where rank=1 
) as v1 inner join (
    select someId, intCol from ExpensiveView where rank=2 
) as v2 on v1.someId = v2.someId 

一個例子的結果集:

some random string, 5, 10 
other random string, 15, 15 

這工作,但它是緩慢的,因爲我有從ExpensiveView選擇兩次。我想要做的是使用case語句只從ExpensiveView中選擇一次。

例如:

select someId, 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

然後我可以組上述結果通過someId並獲得幾乎同樣的事情,第一個查詢:

select sum(rank1IntCol), sum(rank2Intcol) 
from (*the above query*) SubQueryData 
group by someId 

的問題是varCharCol1我需要得到什麼時候排名是1.我不能在組中使用它,因爲當排名爲1時,該列將包含不同的值,而不是排名爲2時。

有沒有人有任何解決方案來優化查詢,所以它只從ExpensiveView中選擇一次,仍然能夠獲取varchar數據?

在此先感謝。

回答

3

很難猜測,因爲我們沒有看到您的視圖定義,但試試這個:

SELECT MIN(CASE rank WHEN 1 THEN v1.varCharCol1 ELSE NULL END), 
     SUM(CASE rank WHEN 1 THEN rank1IntCol ELSE 0 END), 
     SUM(CASE rank WHEN 2 THEN rank2IntCol ELSE 0 END) 
FROM query 
GROUP BY 
     someId 

注意,在大多數情況下,查詢是這樣的:

SELECT * 
FROM mytable1 m1 
JOIN mytable1 m2 
ON  … 

SQL Server優化只會建立一個Eager Spool(臨時索引),稍後將用於搜索JOIN條件,因此這些技巧可能是多餘的。

+0

當對其中存在的NULL一個varchar使用MIN,被的NULL忽略? – bugfixr 2009-08-17 15:07:23

+0

'@ Chu':是的。 – Quassnoi 2009-08-17 15:20:44

+0

好的,我實現了這個,它工作的很棒!我的舊查詢返回515行花了6秒鐘執行。使用這種情況下,它只有幾毫秒。 關於Eagar假脫機...我不知道爲什麼,但似乎SQL Server沒有對原始查詢執行Eager假脫機。這可能與這樣一個事實有關,即查詢實際上是子查詢,或者where子句將其搞亂。 無論如何,謝謝你的提示! – bugfixr 2009-08-17 16:43:05

0
select someId, 
    case when rank = 1 then varCharCol1 else '_' as varCharCol1 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

然後用分鐘()或最大在封閉查詢