rank() over(partition)的使用
rank() over(partition)的使用
有的時候會遇到這樣的問題,我們需要查詢一張表,而且要按照業務排序,比如我需要如下的結果:
地區 日期 費用 產品編號 使用者編號
290 201202 258 1 s1
290 201202 200 1 s5
290 201202 100 1 s100
290 201202 90 2 s7
290 201202 88 2 s9
290 201202 10 2 s12。
領導讓我出一張報表,需要看到每一個業務的收費前三名是那些客戶。這個時候用rank() over(partition)是一個很不錯的選擇。
我的測試表就像上面例子中的表一樣,不過資料稍微多一點點。給大家一個截圖:
可以看到我每一個專案都有5條記錄,我只取前三,那麼SQL如下:
SELECT A.AREA_ID, A.ACCT_MONTH, A.FEE, A.ITEM_ID, A.USER_ID FROM (SELECT T.AREA_ID, T.ACCT_MONTH, T.FEE, T.ITEM_ID, T.USER_ID, RANK() OVER(PARTITION BY T.ITEM_ID ORDER BY T.FEE DESC) RK FROM TEST T) A WHERE RK < 4;
該語句執行的結果就是上述的情況了。
一不做二不休,我順便檢視一下該語句的執行計劃好了。
首先寫一下我的建表語句:
CREATE TABLE TEST ( area_id NUMBER, acct_month NUMBER, fee NUMBER, item_id NUMBER ) PARTITION BY LIST(area_id) ( PARTITION part_290 VALUES('290'), PARTITION part_910 VALUES('910'), PARTITION part_911 VALUES('911'), partition part_912 values('912'), partition part_913 values('913'), partition part_914 values('914'), partition part_915 values('915'), partition part_916 values('916'), partition part_917 values('917'), partition part_919 values('919'), partition part_default values(default) )
我按照地域進行了分割槽,其實也可以按照時間進行分割槽。explain一下plan:
可以看到,只有10條記錄的表,COST卻高達4,不得不說採取這個辦法會極大地降低查詢的效率。但是業務上需要的話,rank() over確實是一個很好使的玩意兒。
加兩條資料進去,順便測測分割槽表是否真的可以在沒有索引的情況下提高一點點效率。加了兩條資料,area_id是911,陝西省寶雞市的區號:0911。語句也稍微變動一下:
SELECT A.AREA_ID, A.ACCT_MONTH, A.FEE, A.ITEM_ID, A.USER_ID FROM (SELECT T.AREA_ID, T.ACCT_MONTH, T.FEE, T.ITEM_ID, T.USER_ID, RANK() OVER(PARTITION BY T.ITEM_ID ORDER BY T.FEE DESC) RK FROM TEST T WHERE t.area_id = 290) A WHERE RK < 4;
explain一下plan:
發現雖然現在是12行資料,但是因為我只查詢西安市(290),所以在rows裡仍舊只是10行,沒有新新增的寶雞市的2行。由此可見,在面對非常海量的資料儲存時,按照一定的條件建立分割槽,是十分有必要的。不過按照時間建立分割槽可能會稍微麻煩點,因為時間在不停的推進,多少年之後,你現在建立的分割槽就已經不可能再用了,就要新增新的分割槽進去,這也是一個挺討厭的事情。