2013-05-31 76 views
1

我是相對較新的SQL,我希望對此有所幫助。基本上,我試圖在查詢中做一些計算,因爲函數有點慢。你們能改進嗎?如何優化此T-SQL查詢?

-- Query to retrive ADA from every school 
Select Distinct DY, 
     DATENAME(MM,DT) as 'Month', 
     CONVERT(nvarchar,DT,101) as 'Date', 
     (
      Select ((@M_stu - (Select Count(SC) from dbo.ATT where sc=1 AND al!='' AND DY=T.DY))/@M_stu)*100 
     ) as 'Merced ADA', 
     (
      Select ((@A_stu - (Select Count(SC) from dbo.ATT where sc=2 AND al!='' AND DY=T.DY))/@A_stu)*100 
     ) as 'Atwater ADA', 
     (
      Select ((@L_stu - (Select Count(SC) from dbo.ATT where sc=3 AND al!='' AND DY=T.DY))/@L_stu)*100 
     ) as 'Livingston ADA', 
     (
      Select ((@B_stu - (Select Count(SC) from dbo.ATT where sc=4 AND al!='' AND DY=T.DY))/@B_stu)*100 
     ) as 'Buhach ADA', 
     (
      Select ((@Y_stu - (Select Count(SC) from dbo.ATT where sc=5 AND al!='' AND DY=T.DY))/@Y_stu)*100 
     ) as 'Yosemite ADA', 
     (
      Select ((@I_stu - (Select Count(SC) from dbo.ATT where sc=6 AND al!='' AND DY=T.DY))/@I_stu)*100 
     ) as 'Independence ADA', 
     (
      Select ((@G_stu - (Select Count(SC) from dbo.ATT where sc=10 AND al!='' AND DY=T.DY))/@G_stu)*100 
     ) as 'Golden Valley ADA', 
     (
      Select ((@S_stu - (Select Count(SC) from dbo.ATT where sc=92 AND al!='' AND DY=T.DY))/@S_stu)*100 
     ) as 'Sequoia ADA' 
From dbo.ATT as T 
Order by DY ASC 

回答

3

試試這個

Select DY, 
     DATENAME(MM,DT) as 'Month', 
     CONVERT(nvarchar,DT,101) as 'Date', 
     @M_stu - (Count(case when sc=1 AND al!='' AND DY=T.DY then 1 else null end)/@M_stu)*100 as 'Merced ADA', 
     @A_stu - (Count(case when sc=2 AND al!='' AND DY=T.DY then 1 else null end)/@A_stu)*100 as 'Atwater ADA', 
     ... 
From dbo.ATT as T 
GROUP BY DY, DT 
Order by DY ASC 
+3

刪除'Distinct'並添加'Group BY DY',您將(幾乎)擁有它。 – RBarryYoung

+0

這很好。它絕對可以改善我的查詢。我決定把代碼放到一個View中來調用這個查詢,就好像它是一個普通的表一樣,但是現在我無法在查詢中保持常量(@M_stuct)。你知道這個方法嗎? – rne1223

+0

@ me1223不,您不能在視圖中使用參數,但可以使用表函數。 http://stackoverflow.com/questions/1687279/can-we-pass-parameter-to-a-view-in-sql –

3

嘗試這種解決方案:

SELECT DISTINCT 
     t.DY       AS DY, 
     DATENAME(MM,t.DT)    AS [Month], 
     CONVERT(NVARCHAR,t.DT,101)  AS [Date], 
     ((@M_stu - d.[1])/@M_stu)*100 AS [Merced ADA], 
     ((@A_stu - d.[2])/@A_stu)*100 AS [Atwater ADA], 
     ((@L_stu - d.[3])/@L_stu)*100 AS [Livingston ADA], 
     ((@B_stu - d.[4])/@B_stu)*100 AS [Buhach ADA], 
     ((@Y_stu - d.[5])/@Y_stu)*100 AS [Yosemite ADA], 
     ((@I_stu - d.[6])/@I_stu)*100 AS [Independence ADA], 
     ((@G_stu - d.[10])/@G_stu)*100 AS [Golden Valley ADA], 
     ((@S_stu - d.[92])/@S_stu)*100 AS [Sequoia ADA] 
FROM dbo.ATT AS t 
OUTER APPLY (
    SELECT c.* 
    FROM (
     SELECT a.sc 
     FROM dbo.ATT AS a 
     WHERE a.sc IN (1,2,3,4,5,6,10,92) 
     AND  a.al!='' 
     AND  a.DY=t.DY 
    ) b 
    PIVOT(COUNT(b.sc) FOR a.sc IN ([1],[2],[3],[4],[5],[6],[10],[92])) c 
) d 
ORDER BY t.DY ASC; 

您也應該檢查,如果你有以下指標之一:CREATE [UNIQUE] INDEX index_name ON dbo.ATT (DY, sc, al)CREATE [UNIQUE] INDEX index_name ON dbo.ATT (DY, sc) INCLUDE (al)

+0

不幸的是,現在對我來說這太複雜了。你能告訴我爲什麼你決定使用OUTER APPLY嗎? – rne1223

+0

你想知道爲什麼我使用'OUTER APPLY'而不是'CROSS APPLY',或者你想知道'OUTER APPLY'是否比這8個子查詢更好? 1)如果'DY'列允許並且包含'NULLs',使用'CROSS APPLY'可能會鬆散行。 2)「外部應用」解決方案非常緊湊,根據我的經驗,「PIVOT」執行計劃往往表現良好。當然,你應該測試和決定自己。當你有與性能相關的問題時,你應該發佈所有索引以獲得正確答案。 –

+0

好的,謝謝。我仍然有點新寫sql查詢,所以我儘量保持對我的可讀性。最有可能的是,一旦我獲得經驗,我將能夠正確使用OUTER APPLY。再次感謝您 – rne1223

1

你必須比較您當前查詢的結果,但是這是我怎麼可能會做到這一點:

Select Distinct DY, 
     DATENAME(MM,DT) as Month, 
     CONVERT(char(10),DT,101) as Date, 
     @M_stu - sum(case when sc=1 then 1.0 else 0.0 end)/@M_stu)*100 as [Merced ADA], 
     @A_stu - sum(case when sc=2 then 1.0 else 0.0 end)/@A_stu)*100 as [Atwater ADA], 
     @L_stu - sum(case when sc=3 then 1.0 else 0.0 end)/@L_stu)*100 as [Livingston ADA], 
     @B_stu - sum(case when sc=4 then 1.0 else 0.0 end)/@B_stu)*100 as [Buhach ADA], 
     @Y_stu - sum(case when sc=5 then 1.0 else 0.0 end)/@Y_stu)*100 as [Yosemite ADA], 
     @I_stu - sum(case when sc=6 then 1.0 else 0.0 end)/@I_stu)*100 as [Independence ADA], 
     @G_stu - sum(case when sc=10 then 1.0 else 0.0 end)/@G_stu)*100 as [Golden Valley ADA], 
     @S_stu - sum(case when sc=92 then 1.0 else 0.0 end)/@S_stu)*100 as [Sequoia ADA] 
From dbo.ATT as T 
Where al!='' 
Order by DY ASC 

而不必樣本數據來進行測試,我認爲這將是最簡單的方法採取。

+0

您如何將它放在視圖中? – rne1223

+0

將創建視圖與之前的select語句放在一起,並將其排序 – BAReese