MSSQL 基礎知識 開窗函式over(),orcl分析函式over()
聚合函式,都是統計中都是不包括NULL值的。
唯獨,count(*)包括NULL值。(注:count(欄位)不包括NULL值。)
開窗函式:
與 聚 合函式一樣,開窗函式也是對行集組進行聚合計算,但是它不像普通聚合函式那樣
每組只返回一個值,開窗函式可以為每組返回多個值,因為開窗函式所執行聚合計算的行
集組是視窗。在ISO SQL規定了這樣的函式為開窗函式,在 Oracle中則被稱為分析函式,
而在DB2中則被稱為OLAP函式。
開窗函式的呼叫格式:
函式名(列)OVER(選項)
OVER關鍵字表示把函式當成開窗函式不是聚合函式。
SQL標準允許將所有聚合函式做成開窗函式,使用OVER關鍵字來區分這兩種用法。
如:開窗函式COUNT(*) OVER()對於查詢結果的每一行都返回所有符合條件的行的條數。
OVER關鍵字後的括號中還經常新增選項用以改變進行聚合執行的視窗範圍。如果OVER關鍵字後的括號中的選項為空,則開窗函式會對結果集中的所有行進行聚合運算。
分析函式的形式
分析函式帶有一個開窗函式over(),包含三個分析子句:分組(partition by), 排序(order by), 視窗(rows) ,他們的使用形式如下:over(partition by xxx order by yyy rows between zzz)。
注:視窗子句在這裡我只說rows方式的視窗,range方式和滑動視窗也不提
分析函式例子(在scott使用者下模擬)
示例目的:顯示各部門員工的工資,並附帶顯示該部分的最高工資。
--顯示各部門員工的工資,並附帶顯示該部分的最高工資。SELECT E.DEPTNO, E.EMPNO, E.ENAME, E.SAL, LAST_VALUE(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL ROWS --unbounded preceding and unbouned following針對當前所有記錄的前一條、後一條記錄,也就是表中的所有記錄--unbounded:不受控制的,無限的 --preceding:在...之前 --following:在...之後 BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) MAX_SAL FROM EMP E;
執行結果:
示例目的:按照deptno分組,然後計算每組值的總和
SELECT EMPNO, ENAME, DEPTNO, SAL, SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME) max_sal FROM SCOTT.EMP;
執行結果:
示例目的:對各部門進行分組,並附帶顯示第一行至當前行的彙總
SELECT EMPNO, ENAME, DEPTNO, SAL, --注意ROWS BETWEEN unbounded preceding AND current row 是指第一行至當前行的彙總 SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_sal FROM SCOTT.EMP;
執行結果:
示例目標:當前行至最後一行的彙總
SELECT EMPNO, ENAME, DEPTNO, SAL, --注意ROWS BETWEEN current row AND unbounded following 指當前行到最後一行的彙總 SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) max_sal FROM SCOTT.EMP;
執行結果:
示例目標:當前行的上一行(rownum-1)到當前行的彙總
SELECT EMPNO, ENAME, DEPTNO, SAL, --注意ROWS BETWEEN 1 preceding AND current row 是指當前行的上一行(rownum-1)到當前行的彙總 SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) max_sal FROM SCOTT.EMP;
執行結果:
示例目標: 當前行的上一行(rownum-1)到當前行的下輛行(rownum+2)的彙總
SELECT EMPNO, ENAME, DEPTNO, SAL, --注意ROWS BETWEEN 1 preceding AND 1 following 是指當前行的上一行(rownum-1)到當前行的下輛行(rownum+2)的彙總 SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN 1 PRECEDING AND 2 FOLLOWING) max_sal FROM SCOTT.EMP;
執行結果:
1.1、兩個order by的執行時機
分析函式(以及與其配合的開窗函式over())是在整個sql查詢結束後(sql語句中的order by的執行比較特殊)再進行的操作, 也就是說sql語句中的order by也會影響分析函式的執行結果:
a) 兩者一致:如果sql語句中的order by滿足與分析函式配合的開窗函式over()分析時要求的排序,即sql語句中的order by子句裡的內容和開窗函式over()中的order by子句裡的內容一樣,
那麼sql語句中的排序將先執行,分析函式在分析時就不必再排序;
b) 兩者不一致:如果sql語句中的order by不滿足與分析函式配合的開窗函式over()分析時要求的排序,即sql語句中的order by子句裡的內容和開窗函式over()中的order by子句裡的內容不一樣,
那麼sql語句中的排序將最後在分析函式分析結束後執行排序。
1.2、開窗函式over()分析函式中的分組/排序/視窗
開窗函式over()分析函式包含三個分析子句:分組子句(partition by), 排序子句(order by), 視窗子句(rows)
視窗就是分析函式分析時要處理的資料範圍,就拿sum來說,它是sum視窗中的記錄而不是整個分組中的記錄,因此我們在想得到某個欄位的累計值時,我們需要把視窗指定到該分組中的第一行資料到當前行, 如果你指定該視窗從該分組中的第一行到最後一行,那麼該組中的每一個sum值都會一樣,即整個組的總和。
視窗子句在這裡我只說rows方式的視窗,range方式和滑動視窗也不提。
視窗子句中我們經常用到指定第一行,當前行,最後一行這樣的三個屬性:
第一行是 unbounded preceding,
當前行是 current row,
最後一行是 unbounded following,
註釋:
當開窗函式over()出現分組(partition by)子句時,
unbounded preceding即第一行是指表中一個分組裡的第一行, unbounded following即最後一行是指表中一個分組裡的最後一行;
當開窗函式over()省略了分組(partition by)子句時,
unbounded preceding即第一行是指表中的第一行, unbounded following即最後一行是指表中的最後一行。
視窗子句不能單獨出現,必須有order by子句時才能出現,
例如:
last_value(sal) over(partition by deptno order by sal rows between unbounded preceding and unbounded following)
以上示例指定視窗為整個分組。而出現order by子句的時候,不一定要有視窗子句,但效果會很不一樣,此時的視窗預設是當前組的第一行到當前行!
如果省略分組,則把全部記錄當成一個組。a) 如果存在order by則預設視窗是unbounded preceding and current row --當前組的第一行到當前行
b) 如果這時省略order by則視窗預設為unbounded preceding and unbounded following --整個組
而無論是否省略分組子句,如下結論都是成立的:
1、視窗子句不能單獨出現,必須有order by子句時才能出現。
2、當省略視窗子句時:
a) 如果存在order by則預設的視窗是unbounded preceding and current row --當前組的第一行到當前行,即在當前組中,第一行到當前行
b) 如果同時省略order by則預設的視窗是unbounded preceding and unbounded following --整個組
所以,
lag(sal) over(order by sal) 解釋
over(order by salary)表示意義如下:
首先,我們要知道由於省略分組子句,所以當前組的範圍為整個表的資料行,
然後,在當前組(此時為整個表的資料行)這個範圍裡執行排序(即order by salary),
最後,我們知道分析函式lag(sal)在當前組(此時為整個表的資料行)這個範圍裡的視窗範圍為當前組的第一行到當前行,即分析函式lag(sal)在這個視窗範圍執行。
轉自,點選檢視原文