【Orcale】分析函數 OVER(PARTITION BY... ORDER BY...)的講解

OVER(PARTITION BY... ORDER BY...)的使用說明和意義

這個函數長這個樣子:OVER(PARTITION BY... ORDER BY...)

顧名思義,PARTITION 中文是分割的意思,ORDER 是排序的意思,所以翻譯一下就是先把一組數據按照制定的字段進行分割成各種組,然後組內按照某個字段排序。

以實際案例來說明這個函數的使用,

首先,我們先看一組普通排序的數據:


然後對其進行新加一個僞劣ROWNUM,看看數據原本的順序:


OVER(ORDER BY ...)的意思是以按照某個字段排序,所以和直接對錶的order by效果是一樣的:


這裏就顯示了OVER(ORDER BY ...)的第一個功能,就是對新查詢得到的數據進行重新編號,即RNO的值,由於這裏沒有PARTITION BY...,所以可以比作整個列就是一個大塊,然後對大塊的內容進行排序,這個時候再加上PARTITION BY...,查詢結果:


它會按照制定的字段,把相同值的排在一起,分爲一個塊,也就是分組,然後組內排序編號,這樣你就可以取不同組內的任意第幾個值,類似於TOP-N的分析。

在這裏over之前使用的函數是ROW_NUMBER(),就是對數據的編號。


與OVER(PARTITION BY... ORDER BY...)匹配使用的函數

row_number() over()、rank() over()和dense_rank() over()

在上面的例子裏,使用ROW_NUMBER()可以對數據編號,但是有一個問題,例子中的MI_ID是不可以重複的,如果在可以重複的情況下,就有並列的情況,這樣就無法取出並列的數據,只能取單一排序的數據。所以這裏可以換成 rank() over()和dense_rank() over()來進行編號:(rank() over()和dense_rank() over()的區別如圖)



sum() over(),first_value() over()和last_value() over()的使用

sum() over()分組求和

first_value() over()求分組第一條

last_value() over()求分組最後一條

其中用row_number() over()取編號第一條的也可以實現first_value() over()的效果

[sql] view plain copy
  1. SELECT DISTINCT *  
  2.   FROM (SELECT T1.MI_ID,  
  3.                T3.I_IDENTITY_CARD,  
  4.                SUM(NVL(T2.IS_VISHEARTPROMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) PRO_NUM,  
  5.                SUM(NVL(T2.IS_VISHEARTEXPMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) EXP_NUM,  
  6.                SUM(NVL(T2.IS_VISHEARTPOLMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) POL_NUM,  
  7.                              T1.CREATE_TIME,  
  8.                <span style="color:#ff0000;">FIRST_VALUE</span>(T2.CREATE_DATE) OVER(PARTITION BY T3.I_IDENTITY_CARD ORDER BY T2.CREATE_DATE DESC) FIRST_CREATE_DATE  
  9.           FROM T_ZZ_PETITIONERS T1  
  10.           LEFT JOIN T_ZZ_VISIT_RECORD T2  
  11.             ON T1.CI_RS_ID = T2.CI_RS_ID  
  12.            AND T2.STATUS != '003'  
  13.           LEFT JOIN T_DC_CI_RS_TOP T3  
  14.             ON T1.CI_RS_ID = T3.CI_RS_ID  
  15.            AND T3.STATUS = '1'  
  16.          WHERE T1.IS_ADD_HEARTPROTECT = '1'  
  17.            AND T1.STATUS = '1') C  
  18.  ORDER BY C.CREATE_TIME DESC  


[sql] view plain copy
  1. SELECT *  
  2.   FROM (SELECT T1.MI_ID,  
  3.                T3.I_IDENTITY_CARD,  
  4.                SUM(NVL(T2.IS_VISHEARTPROMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) PRO_NUM,  
  5.                SUM(NVL(T2.IS_VISHEARTEXPMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) EXP_NUM,  
  6.                SUM(NVL(T2.IS_VISHEARTPOLMEMBER, 0)) OVER(PARTITION BY T3.I_IDENTITY_CARD) POL_NUM,  
  7.                T1.CREATE_TIME,  
  8.                <span style="color:#ff0000;">ROW_NUMBER()</span> OVER(PARTITION BY T3.I_IDENTITY_CARD ORDER BY T2.CREATE_DATE DESC) RNO  
  9.           FROM T_ZZ_PETITIONERS T1  
  10.           LEFT JOIN T_ZZ_VISIT_RECORD T2  
  11.             ON T1.CI_RS_ID = T2.CI_RS_ID  
  12.            AND T2.STATUS != '003'  
  13.           LEFT JOIN T_DC_CI_RS_TOP T3  
  14.             ON T1.CI_RS_ID = T3.CI_RS_ID  
  15.           LEFT JOIN T_DC_GRID T4  
  16.             ON T1.REGION_CODE = T4.INFO_ORG_CODE  
  17.          WHERE T1.IS_ADD_HEARTPROTECT = '1'  
  18.            AND T1.STATUS = '1'  
  19.            AND T3.STATUS = '1'  
  20.            AND T4.STATUS = '001') C  
  21.  WHERE <span style="color:#ff0000;">C.RNO = 1</span>  
  22.  ORDER BY C.CREATE_TIME DESC  


ignore nulls:過濾掉空值


常用的分析函數如下所列:

row_number() over(partition by ... order by ...)
rank() over(partition by ... order by ...)
dense_rank() over(partition by ... order by ...)
count() over(partition by ... order by ...)
max() over(partition by ... order by ...)
min() over(partition by ... order by ...)
sum() over(partition by ... order by ...)
avg() over(partition by ... order by ...)
first_value() over(partition by ... order by ...)
last_value() over(partition by ... order by ...)
lag() over(partition by ... order by ...)

lead() over(partition by ... order by ...)

  • row_number()和rownum差不多,功能更強一點(可以在各個分組內從1開時排序).
  • rank()是跳躍排序,有兩個第二名時接下來就是第四名(同樣是在各個分組內).
  • dense_rank()l是連續排序,有兩個第二名時仍然跟着第三名。相比之下row_number是沒有重複值的.
  • lag(arg1,arg2,arg3):
  1. arg1是從其他行返回的表達式
  2. arg2是希望檢索的當前行分區的偏移量。是一個正的偏移量,是一個往回檢索以前的行的數目。
  3. arg3是在arg2表示的數目超出了分組的範圍時返回的值。

小結:

項目中用到這個東西,網上看到這篇文章覺得還不錯,作爲記錄,也分享給大家。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章