1. 程式人生 > 其它 >函式(開窗函式)

函式(開窗函式)

技術標籤:筆記sql資料庫

一.概述

開窗函式又叫分析函式

開窗函式用於定義一個視窗(這裡的視窗是指運算將要操作的資料集合),它對一組值進行操作,
不需要使用GROUP BY子句對資料進行分組,能夠在同一行中同時返回對於一組值的處理結果。

兩者區別:

聚合函式:將資料按照一定的規則分組,統一分析各組的某項情況,每個分組返回一行結果
開窗函式:將資料按照一定的規則分組,統一分析各組的某項情況,每行資料返回一行結果

二.語法
–不加視窗範圍
函式名()OVER(PARTITION BY COLUMN1 ORDER BY COLUMN2)

分析:
1.PARTITION BY COLUMN1->指明 按照COLUMN1分組

2.ORDER BY COLUMN2->按照COLUMN2列排序
3.分組、排序規則遵循分組排序查詢的規則
4.OVER 為開窗函式的標誌

三.分類
1.聚合類開窗函式(聚合函式和視窗組合)
SUM/MIN/MAX/AVG/COUNT(COLUMN1)OVER(PARTITION BY COLUMN1 ORDER BY COLUMN2);

示例:
查詢各個部門的員工編號,姓名,以及各部門的平均薪資
–表連線
SELECT EMPNO, ENAME, AVG_SAL,e.deptno
FROM EMP E,
(SELECT DEPTNO, AVG(SAL) AVG_SAL FROM EMP GROUP BY DEPTNO) D

WHERE E.DEPTNO = D.DEPTNO;

 SELECT TABLE_NAME FROM USER_TABLES;

–開窗函式
SELECT EMPNO,ENAME,JOB,DEPTNO,AVG(SAL)OVER(PARTITION BY DEPTNO) AVG_SAL FROM EMP;

2.排序類開窗函式(用於排序,實現組內排序)
–查詢各個部門前兩名的員工的工資

ROW_NUMBER() RANK() DENSE_RANK()

示例:
SELECT EMPNO,ENAME,JOB,SAL,DEPTNO,ROW_NUMBER()OVER(ORDER BY SAL) AVG_SAL FROM EMP;–類似於ROWNUM

SELECT EMPNO,ENAME,JOB,SAL,DEPTNO,ROW_NUMBER()OVER(PARTITION BY DEPTNO ORDER BY SAL) AVG_SAL FROM EMP;–類似於ROWNUM

四.聚合類開窗函式
1.函式名(引數)OVER()

SELECT EMPNO,ENAME,JOB,DEPTNO,SUM(SAL)OVER() AVG_SAL FROM EMP;–返回公司全體工資和
SELECT EMPNO,ENAME,JOB,DEPTNO,SUM()OVER() AVG_SAL FROM EMP;–報錯 引數個數無效

–函式名後必須要含有分析的列

  1. 函式名()OVER()

SELECT EMPNO,ENAME,JOB,DEPTNO,SUM(SAL)OVER() AVG_SAL FROM EMP;–返回公司全體工資和
–若OVER後括號內沒有引數,,以整張表為一組分析

3.函式名()OVER(分組引數 )

SELECT EMPNO,ENAME,JOB,DEPTNO,SUM(SAL)OVER(PARTITION BY DEPTNO) FROM EMP;–返回各個部門工資和
SELECT EMPNO,ENAME,JOB,SAL,DEPTNO,SUM(SAL)OVER(PARTITION BY DEPTNO,JOB) FROM EMP;–返回各個部門各工種工資和

SELECT EMPNO,ENAME,JOB,DEPTNO,SUM(SAL)OVER(PARTITION BY 1) FROM EMP;–返回工資和

–含有分組引數,按照分組列分組統計,返回函式的結果

  1. 函式名()OVER(排序引數 )

SELECT EMPNO,ENAME,SAL,JOB,DEPTNO,SUM(SAL)OVER(ORDER BY SAL) FROM EMP;
SELECT EMPNO,ENAME,SAL,JOB,DEPTNO,COUNT(SAL)OVER(ORDER BY SAL) FROM EMP;

–含有排序引數,實現累加的效果,若遇到排序列相同的資料,會將所有相同的資料統計,然後在相同的資料後返回同一結果

5.函式名()OVER(分組引數 排序引數 )

SELECT EMPNO,ENAME,SAL,JOB,DEPTNO,SUM(SAL)OVER(PARTITION BY DEPTNO ORDER BY SAL) FROM EMP;
–實現組內累加,結果處理同上

6.作為條件使用
SELECT EMPNO, ENAME, SAL, JOB, DEPTNO, SUM(SAL) OVER(ORDER BY SAL)
FROM EMP
WHERE SUM(SAL) OVER(ORDER BY SAL) > 20000;–報錯 不允許使用分組函式

SELECT *
FROM (SELECT EMPNO,
ENAME,
SAL,
JOB,
DEPTNO,
SUM(SAL) OVER(ORDER BY SAL) SMO
FROM EMP)
WHERE SMO > 20000;

–作為條件時,開窗函式需要和子查詢聯合使用

五.排序類開窗函式

1.三種函式的區分

ROW_NUMBER():將資料按照排序列進行排序,生成一組從1開始,遞增的陣列
RANK() :將資料按照排序列進行排序,遇到相同的資料,序號相同,下一條資料序號不連續
DENSE_RANK():將資料按照排序列進行排序,遇到相同的資料,序號相同,下一條資料序號連續

示例:
1).將員工表中的工資列排序
SELECT EMPNO,ENAME,SAL,ROW_NUMBER()OVER(ORDER BY SAL) FROM EMP;–一組從1開始,遞增的陣列

SELECT EMPNO,ENAME,SAL,RANK()OVER(ORDER BY SAL) FROM EMP;--排序 ,遇到相同的資料,序號相同,下一條資料序號不連續

SELECT EMPNO,ENAME,SAL,DENSE_RANK()OVER(ORDER BY SAL) FROM EMP;--排序 ,遇到相同的資料,序號相同,下一條資料序號連續

2.函式名(引數)OVER()

SELECT EMPNO,ENAME,JOB,DEPTNO,ROW_NUMBER(SAL)OVER() AVG_SAL FROM EMP;–缺失右括號
SELECT EMPNO,ENAME,JOB,DEPTNO,ROW_NUMBER()OVER() AVG_SAL FROM EMP;–報錯 丟失ORDER BY表示式
SELECT EMPNO,ENAME,JOB,DEPTNO,ROW_NUMBER()OVER(ORDER BY SAL) AVG_SAL FROM EMP;–報錯 丟失ORDER BY表示式

–函式名後括號不含有引數,排序類函式必須要有ORDER BY表示式

3.函式名()OVER(分組引數 排序引數)

SELECT EMPNO,ENAME,JOB,DEPTNO,ROW_NUMBER()OVER(ORDER BY SAL PARTITION BY DEPTNO) FROM EMP;
SELECT EMPNO,ENAME,JOB,DEPTNO,ROW_NUMBER()OVER( PARTITION BY DEPTNO ORDER BY SAL) FROM EMP;

–含有排序引數 、分組引數,按照組內排序列排序
–分組引數在排序引數之前

4.作為條件使用
SELECT EMPNO, ENAME, SAL, JOB, DEPTNO, ROW_NUMBER() OVER(ORDER BY SAL)
FROM EMP
WHERE ROW_NUMBER() OVER(ORDER BY SAL) > 20000;–報錯 函式在此禁用

SELECT *
FROM (SELECT EMPNO,
ENAME,
SAL,
JOB,
DEPTNO,
ROW_NUMBER() OVER(ORDER BY SAL) SMO
FROM EMP)
WHERE SMO > 5;

–作為條件時,開窗函式需要和子查詢聯合使用

六.兩者注意點

聚合類開窗函式注意點:

1)分析函式名內必須包含需要分析的內容
2)分析子句沒有硬性要求
3)採用預設視窗範圍時,下一個相同值會被一併算入
4)不能寫在WHERE 後面 起別名在WHERE後無效

排序類開窗函式注意點

1)分析函式不包含需要分析的內容
2)對於分析字句,視窗字句最少得有排序子句
3)ROW_NUMBER() RANK() DENSE_RANK()區別
4)不能直接寫在WHERE 後,WHERE後起別名也無效

七.新增視窗範圍

1.用於限制分析函式分析的資料條數

2.語法
函式名()OVER(分組子句 排序子句 視窗範圍)

視窗範圍:
ROWS BETWEEN [UNBOUNDED PRECEDING][N PRECEDING] AND [N FOLLOWING ][UNBOUNDED FOLLOWING][CURRENT ROW])

UNBOUNDED 沒有限制,無邊界的
PRECEDING 之前的
FOLLOWING 之後的
CURRENT 當前的
ROW 行

示例:
–不同的作用範圍組合

ROWS BETWEEN N PRECEDING AND N FOLLOWING —當前行的前N行到當前行的後N行(包括當前行)
ROWS BETWEEN CURRENT ROW AND N FOLLOWING —當前行到當前行的後N行(包括當前行)
ROWS BETWEEN N PRECEDING AND CURRENT ROW —當前行的前N行到當前行(包括當前行)
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW —從頭到當前行
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING —從當前行到最後
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING —從頭到尾
ROWS BETWEEN UNBOUNDED PRECEDING AND N FOLLOWING —從頭到當前行的後N行(包括當前行)
ROWS BETWEEN N PRECEDING AND UNBOUNDED FOLLOWING —當前行的前N行到末尾(包括當前行)

1).統計員工表中的累加工資和
SELECT EMPNO,ENAME,SAL,SUM(SAL)OVER(ORDER BY SAL) FROM EMP;

SELECT EMPNO,
ENAME,
SAL,
SUM(SAL) OVER(ORDER BY SAL ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM EMP;

2).統計2020/08/25前後三天的銷售總額

SELECT * FROM PRODUCT_ORDER;

SELECT *
FROM (SELECT SALE_DATE,
SUM(AMOUNT) OVER(ORDER BY SALE_DATE ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING)
FROM PRODUCT_ORDER)
WHERE SALE_DATE = TO_DATE(‘2020/08/25’, ‘YYYY/MM/DD’);