SQL 研究 - Cube 和 RollUp

使用Pivot,你終於滿足了老闆的要求,生成了各個投資人在Asia和Europe的投資統計表。在讚許的同時,他又提出新的需求:

需要統計每個投資方在各個地區的投資總和,各個投資方的所有投資,以及各個地區所吸引的所有投資。

 

又一次,你跑到數據庫裏,看到如下的表:

CREATE TABLE [dbo].[Investment](
 [Investor] [nvarchar](256) NULL,
 [Capital] [float] NULL,
 [District] [nvarchar](256) NULL
)

 

select * from [dbo].[Investment] 得到如下結果:

Investor Capital District

 IBM 1000000 Asia
IBM 150000 Europe
Oracle 800000 Asia
Oracle 180000 Europe
Microsoft 900000 Asia
Microsoft 180000 Europe
IBM 800000 Europe
Oracle 80000 Asia
Microsoft 70000 Europe

 

於是你自然的想到這樣的方法:

select Investor, Capital, sum(District) from dbo.Investment group by Investor,Capital

union all

select Investor, null, sum(District) from dbo.Investment group by Investor

Union all

select Null, Capital, sum(District) from dbo.Investment group by Capital

 

這樣你當然得到了想要的結果,可是三個語句獨立執行,相互間存在重複的運算,效率必然不高。再者,這裏只有兩個維度,Investor和District,倘若有三個維度,就需要執行7次;4個維度就需要15次。可見這種方法有它的侷限性。

 

正確的做法是什麼呢? 對, Cube,它能自動列出維度列的值所有可能的組合,並計算這些組合對應的聚合函數。

應用Cube來解決上面的問題,我們可以得到如下簡潔的答案:

select Investor, Capital, sum(District)

from dbo.Investment

group by Investor,Capital with Cube

 

它的結果能回答老闆所提出的3個問題,並附贈一行,所有投資方在所有地區的投資總和。

 

當然,寫SQL有時候跟作畫一樣,不能少一筆,也不能多一筆,現在多了這行,也挺難看的。別急,辦法是有的:

select Investor, District, sum(Capital)

from dbo.Investment

group by Investor,Districtwith Cube

Having Grouping(Investor)<>1 or grouping(District)<>1

好吧,Grouping是依附於Cube的一個函數,它用於判斷在當前的分組中,它參數指定的列是不是被置爲null。注意是置爲null,不是本身就是null。

 

當然,聰明如你的讀者,也就明白如果表中存在多個維度列,而你只希望對其中一些做聚合時,該如何使用Cube這一強有力的工具了。

 

當然老闆的要求總是變化多端的,如果老闆只對投資人感興趣,他很可能不要查看Investor被聚合掉的情況,這個時候你需要Rollup,因爲Investor和District此時已不是平等的維度關係,Investor高於後者。

SQL如下:

select Investor, District, sum(Capital)

from dbo.Investment

group by Investor,District with rollup

 

結果如下:

Investor District Capital

 IBM Asia 1000000
IBM Europe 950000
IBM NULL 1950000
Microsoft Asia 900000
Microsoft Europe 250000
Microsoft NULL 1150000
Oracle Asia 880000
Oracle Europe 180000
Oracle NULL 1060000
NULL NULL 4160000

 

跟之前with Cube產生的結果對比,新的結果集不存在Investor爲Null的情況,除了最後一行。如果將上述結果做成一個view,便可以在之上的查詢加入District不爲NULL的條件,最後得到各個Investor的投資總和。

 

 最後,需要注意的是,跟手動編寫的Group by相比,產生相同結果,With Cube要多花10%左右的時間,是什麼原因造成這個性能的差異還需進一步研究。

 

 

 

發佈了36 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章