oracle 之分析函數 over (partition by ...order by ...)

来源:https://www.cnblogs.com/moyijian/archive/2018/11/10/9905803.html
-Advertisement-
Play Games

一:分析函數overOracle從8.1.6開始提供分析函數,分析函數用於計算基於組的某種聚合值,它和聚合函數的不同之處是對於每個組返回多行,而聚合函數對於每個組只返回一行。 1、分析函數和聚合函數的不同之處: 分析函數和聚合函數很多是同名的,意思也一樣,只是聚合函數用group by分組,每個分組 ...


一:分析函數over
Oracle從8.1.6開始提供分析函數,分析函數用於計算基於組的某種聚合值,它和聚合函數的不同之處是對於每個組返回多行,而聚合函數對於每個組只返回一行。

1、分析函數和聚合函數的不同之處:

分析函數和聚合函數很多是同名的,意思也一樣,只是聚合函數用group by分組,每個分組返回一個統計值,而分析函數採用partition by分組,並且每組每行都可以返回一個統計值。簡單的說就是聚合函數返回統計結果,分析函數返回明細加統計結果。

(一)、分析函數語法:
  FUNCTION_NAME(<argument>,<argument>...)
  OVER
  (<Partition-Clause><Order-by-Clause><Windowing Clause>)

例:(在oracle示例庫中演示,用戶scott)
select ename,sum(sal) over (partition by deptno order by ename) new_alias from emp;
a、sum就是函數名(FUNCTION_NAME)
b、(sal)是分析函數的參數,每個函數有0~3個參數,參數可以是表達式,例如:sum(sal+comm)
c、over 是一個關鍵字,用於標識分析函數,否則查詢分析器不能區別sum()聚集函數和sum()分析函數
d、partition by deptno (按相應的值(deptno)進行分組統計)是可選的分區子句,如果不存在任何分區子句,則全部的結果集可看作一個單一的大區
e、order by ename 是可選的order by 子句,有些函數需要它,有些則不需要.依靠已排序數據的那些函數。

即:分析函數帶有一個開窗函數over(),包含三個分析子句:

分組(partition by)
排序(order by)
視窗(rows)

示例1:

SELECT empno,ename,job,deptno,  ----查詢基礎欄位
	COUNT(*) over(PARTITION BY deptno) cnt_dept_man,   --- 查詢部門人員數量	(等同於用部門deptno進行分組查詢)
	COUNT(*) over (PARTITION BY deptno ORDER BY empno) AS sum_dept_add,	 ---	查詢出的部門人員數依次為前一行的求和數加上當前行的行數(若未sum則會是逐行累加的數據)
	COUNT(*) over(PARTITION BY  job) cnt_job_man	,		---查詢崗位的的人員數量	(等同於用崗位job進行分組查詢)
	COUNT(*) over (PARTITION BY job ORDER BY empno) AS sum_job_add ---查詢出崗位人員(依次為前一行的求和數加上當前行的行數(若未sum則會是逐行累加的數據)
FROM emp;

  

 

(二)、FUNCTION子句
ORACLE提供了N多個分析函數,按功能分5類

Oracle分析函數——函數列表

------------------------------------------------------------------------------------------------ 
SUM        :該函數計算組中表達式的累積和
MIN         :在一個組中的數據視窗中查找表達式的最小值
MAX        :在一個組中的數據視窗中查找表達式的最大值
AVG        :用於計算一個組和數據視窗內表達式的平均值。
COUNT   :對一組內發生的事情進行累積計數
-------------------------------------------------------------------------------------------------
RANK            :根據ORDER BY子句中表達式的值,從查詢返回的每一行,計算它們與其它行的相對位置
DENSE_RANK     :根據ORDER BY子句中表達式的值,從查詢返回的每一行,計算它們與其它行的相對位置
FIRST            :從DENSE_RANK返回的集合中取出排在最前面的一個值的行
LAST             :從DENSE_RANK返回的集合中取出排在最後面的一個值的行
FIRST_VALUE   :返回組中數據視窗的第一個值
LAST_VALUE     :返回組中數據視窗的最後一個值。
LAG             :可以訪問結果集中的其它行而不用進行自連接
LEAD             :LEAD與LAG相反,LEAD可以訪問組中當前行之後的行
ROW_NUMBER  :返回有序組中一行的偏移量,從而可用於按特定標準排序的行號
-------------------------------------------------------------------------------------------------
STDDEV         :計算當前行關於組的標準偏離
STDDEV_POP     :該函數計算總體標準偏離,並返回總體變數的平方根
STDDEV_SAMP  :該函數計算累積樣本標準偏離,並返回總體變數的平方根
VAR_POP         :該函數返回非空集合的總體變數(忽略null)
VAR_SAMP      :該函數返回非空集合的樣本變數(忽略null)
VARIANCE       :如果表達式中行數為1,則返回0,如果表達式中行數大於1,則返回VAR_SAMP
COVAR_POP     :返回一對錶達式的總體協方差
COVAR_SAMP  :返回一對錶達式的樣本協方差
CORR           :返回一對錶達式的相關係數
-------------------------------------------------------------------------------------------------
CUME_DIST          :計算一行在組中的相對位置
NTILE               :將一個組分為"表達式"的散列表示
PERCENT_RANK      :和CUME_DIST(累積分配)函數類似
PERCENTILE_DISC     :返回一個與輸入的分佈百分比值相對應的數據值
PERCENTILE_CONT   :返回一個與輸入的分佈百分比值相對應的數據值
RATIO_TO_REPORT   :該函數計算expression/(sum(expression))的值,它給出相對於總數的百分比
REGR_ (Linear Regression) Functions    :這些線性回歸函數適合最小二乘法回歸線,有9個不同的回歸函數可使用
-------------------------------------------------------------------------------------------------
CUBE          :按照OLAP的CUBE方式進行數據統計,即各個維度均需統計
ROLLUP        :

-------------------------------------------------------------------------------------------------

示例2:查詢每個部門工資最高的員工信息

 1、(count,rank,dense_rank,row_number)排名函數的使用及註意事項

在使用排名函數的時候需要註意以下三點:

  (1、排名函數必須有 OVER 子句。

  (2、排名函數必須有包含 ORDER BY 的 OVER 子句。

  (3、分組內從1開始排序。

-- 一般的寫法:
SELECT E.ENAME, E.JOB, E.SAL MAXSAL , E.DEPTNO
  FROM SCOTT.EMP E,
       (SELECT E.DEPTNO, MAX(E.SAL) SAL FROM SCOTT.EMP E GROUP BY E.DEPTNO) ME
 WHERE E.DEPTNO = ME.DEPTNO
   AND E.SAL = ME.SAL;         
     
--  分析函數OVER    (使用count函數用order by將相應數據分組,獲取分組編號)
SELECT ENAME,JOB,MAXSAL,DEPTNO FROM 
(SELECT     ENAME,JOB,MAX(SAL) OVER (PARTITION BY DEPTNO) AS MAXSAL,DEPTNO,
                COUNT(*) OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) AS NUM FROM EMP)
                WHERE NUM = 1;

--析函數OVER    (使用rank函數用order by將相應數據分組,獲取分組編號)
SELECT     E.ENAME,E.JOB,E.SAL,E.DEPTNO    FROM
(SELECT ENAME,JOB,SAL,RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) RANK ,DEPTNO FROM EMP) E            
WHERE  E.RANK = 1 AND NOT deptno IS NULL;

--分析函數OVER    (使用dense_rank函數用order by將相應數據分組,獲取分組編號)
SELECT     E.ENAME,E.JOB,E.SAL,E.DEPTNO    FROM
(SELECT ENAME,JOB,SAL,dense_RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) RANK ,DEPTNO FROM EMP) E            
WHERE  E.RANK = 1 AND NOT deptno IS NULL;            

--分析函數OVER    (使用row_number函數用order by將相應數據分組,獲取分組編號)
SELECT     E.ENAME,E.JOB,E.SAL,E.DEPTNO    FROM
(SELECT ENAME,JOB,SAL,row_number() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) RANK ,DEPTNO FROM EMP) E            
WHERE  E.RANK = 1 AND NOT deptno IS NULL;

 註意事項:

一般寫法與分析函數的主要區別在於:使用分析函數可以提升sql的執行效率,一般寫法是通過兩個或多個表關聯來進行查詢(存在笛卡爾積),而用分析函數則所有的查詢都在一個表中實現,大大提升了sql的查詢效率(主要體現於自身表的關聯查詢)。

row_number的用途非常廣泛,排序最好用它,它會為查詢出來的每一行記錄生成一個序號,依次排序且不會重覆,註意使用row_number函數時必須要用over子句選擇對某一列進行排序才能生成序號。

rank函數用於返回結果集的分區內每行的排名,行的排名是相關行之前的排名數加一。簡單來說rank函數就是對查詢出來的記錄進行排名,與row_number函數不同的是,rank函數考慮到了over子句中排序欄位值相同的情況,如果使用rank函數來生成序號,over子句中排序欄位值相同的序號是一樣的,後面欄位值不相同的序號將跳過相同的排名號排下一個,也就是相關行之前的排名數加一,可以理解為根據當前的記錄數生成序號,後面的記錄依此類推。

dense_rank函數的功能與rank函數類似,dense_rank函數在生成序號時是連續的,而rank函數生成的序號有可能不連續。dense_rank函數出現相同排名時,將不跳過相同排名號,rank值緊接上一次的rank值。在各個分組內,rank()是跳躍排序,有兩個第一名時接下來就是第三名,dense_rank()是連續排序,有兩個第一名時仍然跟著第二名。

count函數用於返回結果集的分區內每行的排名,行的排名是相關行之前的排名數加一,count()是跳躍排序,有兩個第一名時兩個第一名的序號都為2,就沒有第一名,有兩個第二名,接下來就是第三名,dense_rank()是連續排序,有兩個第一名時仍然跟著第二名。

示例3、查詢員工信息的同時,查詢員工工資與所在部門最低、最高工資的差額

2、(min、max)取最值函數的使用及註意事項 

--一般寫法
SELECT
E.ENAME, E.JOB,E.SAL,E.DEPTNO,
    ME.MIN_SAL MIN_SAL,
    ME.MAX_SAL MAX_SAL, E.SAL
- ME.MIN_SAL DIFF_MIN_SAL, ME.MAX_SAL - E.SAL DIFF_MAX_SAL FROM SCOTT.EMP E, (SELECT E.DEPTNO, MIN(E.SAL) MIN_SAL, MAX(E.SAL) MAX_SAL FROM SCOTT.EMP E GROUP BY E.DEPTNO) ME WHERE E.DEPTNO = ME.DEPTNO ORDER BY E.DEPTNO, E.SAL; --使用分析函數: SELECT E.ENAME, E.JOB,E.SAL,E.DEPTNO,
MIN(E.SAL) OVER(PARTITION BY E.DEPTNO) MIN_SAL, MAX(E.SAL) OVER(PARTITION BY E.DEPTNO) MAX_SAL, NVL(E.SAL - MIN(E.SAL) OVER(PARTITION BY E.DEPTNO), 0) DIFF_MIN_SAL, NVL(MAX(E.SAL) OVER(PARTITION BY E.DEPTNO) - E.SAL, 0) DIFF_MAX_SAL FROM EMP E; /*註:這裡沒有排序條件,若加上order by 排序條件, MAX() OVER(PARTITION BY .. ORDER BY .. DESC) 排序規則只能為desc,否則不起作用,將查詢到目前為止排序值最高欄位的對應值 MIN() OVER(PARTITION BY .. ORDER BY .. ASC ) 排序規則只能為asc,否則不起作用,將查詢到目前為止排序值最低的欄位的對應值, 如下:*/ SELECT E.ENAME, E.JOB,E.SAL,E.DEPTNO, MIN(E.SAL) OVER(PARTITION BY E.DEPTNO) MIN_SAL01, MAX(E.SAL) OVER(PARTITION BY E.DEPTNO) MAX_SAL01, MIN(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL) MIN_SAL02, MAX(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL) MAX_SAL02, --不起作用 MIN(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL DESC) MIN_SAL03, --不起作用 MAX(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL DESC) MAX_SAL03, MIN(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL ASC) MIN_SAL04, MAX(E.SAL) OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL ASC) MAX_SAL04, --不起作用 NVL(E.SAL - MIN(E.SAL) OVER(PARTITION BY E.DEPTNO), 0) DIFF_MIN_SAL, NVL(MAX(E.SAL) OVER(PARTITION BY E.DEPTNO) - E.SAL, 0) DIFF_MAX_SAL FROM EMP E;

 

 oracle分析函數-----實驗
--1、GROUP BY子句

--CREATE TEST TABLE AND INSERT TEST DATA.
create table students
(id number(15,0),
area varchar2(10),
stu_type varchar2(2),
score number(20,2));

insert into students values(1, '111', 'g', 80 );
insert into students values(1, '111', 'j', 80 );
insert into students values(1, '222', 'g', 89 );
insert into students values(1, '222', 'g', 68 );
insert into students values(2, '111', 'g', 80 );
insert into students values(2, '111', 'j', 70 );
insert into students values(2, '222', 'g', 60 );
insert into students values(2, '222', 'j', 65 );
insert into students values(3, '111', 'g', 75 );
insert into students values(3, '111', 'j', 58 );
insert into students values(3, '222', 'g', 58 );
insert into students values(3, '222', 'j', 90 );
insert into students values(4, '111', 'g', 89 );
insert into students values(4, '111', 'j', 90 );
insert into students values(4, '222', 'g', 90 );
insert into students values(4, '222', 'j', 89 );
commit;



--A、GROUPING SETS

select id,area,stu_type,sum(score) score
from students
group by grouping sets((id,area,stu_type),(id,area),id)
order by id,area,stu_type;

/*--------理解grouping sets
select a, b, c, sum( d ) from t
group by grouping sets ( a, b, c )

等效於

select * from (
select a, null, null, sum( d ) from t group by a
union all
select null, b, null, sum( d ) from t group by b
union all
select null, null, c, sum( d ) from t group by c
)
*/

--B、ROLLUP

select id,area,stu_type,sum(score) score
from students
group by rollup(id,area,stu_type)
order by id,area,stu_type;

/*--------理解rollup
select a, b, c, sum( d )
from t
group by rollup(a, b, c);

等效於

select * from (
select a, b, c, sum( d ) from t group by a, b, c
union all
select a, b, null, sum( d ) from t group by a, b
union all
select a, null, null, sum( d ) from t group by a
union all
select null, null, null, sum( d ) from t
)
*/

--C、CUBE

select id,area,stu_type,sum(score) score
from students
group by cube(id,area,stu_type)
order by id,area,stu_type;

/*--------理解cube
select a, b, c, sum( d ) from t
group by cube( a, b, c)

等效於

select a, b, c, sum( d ) from t
group by grouping sets(
( a, b, c ),
( a, b ), ( a ), ( b, c ),
( b ), ( a, c ), ( c ),
() )
*/

--D、GROUPING

/*從上面的結果中我們很容易發現,每個統計數據所對應的行都會出現null,
如何來區分到底是根據那個欄位做的彙總呢,grouping函數判斷是否合計列!*/

select decode(grouping(id),1,'all id',id) id,
decode(grouping(area),1,'all area',to_char(area)) area,
decode(grouping(stu_type),1,'all_stu_type',stu_type) stu_type,
sum(score) score
from students
group by cube(id,area,stu_type)
order by id,area,stu_type;

--2、OVER()函數的使用
--1、RANK()、DENSE_RANK() 的、ROW_NUMBER()、CUME_DIST()、MAX()、AVG()

break on id skip 1
select id,area,score from students order by id,area,score desc;

select id,rank() over(partition by id order by score desc) rk,score from students;

--允許併列名次、名次不間斷
select id,dense_rank() over(partition by id order by score desc) rk,score from students;

--即使SCORE相同,ROW_NUMBER()結果也是不同
select id,row_number() over(partition by ID order by SCORE desc) rn,score from students;

select cume_dist() over(order by id) a, --該組最大row_number/所有記錄row_number
row_number() over (order by id) rn,id,area,score from students;

select id,max(score) over(partition by id order by score desc) as mx,score from students;

select id,area,avg(score) over(partition by id order by area) as avg,score from students; --註意有無order by的區別

--按照ID求AVG
select id,avg(score) over(partition by id order by score desc rows between unbounded preceding
and unbounded following ) as ag,score from students;


--2、SUM()

select id,area,score from students order by id,area,score desc;

select id,area,score,
sum(score) over (order by id,area) 連續求和, --按照OVER後邊內容彙總求和
sum(score) over () 總和, -- 此處sum(score) over () 等同於sum(score)
100*round(score/sum(score) over (),4) "份額(%)"
from students;

select id,area,score,
sum(score) over (partition by id order by area ) 連id續求和, --按照id內容彙總求和
sum(score) over (partition by id) id總和, --各id的分數總和
100*round(score/sum(score) over (partition by id),4) "id份額(%)",
sum(score) over () 總和, -- 此處sum(score) over () 等同於sum(score)
100*round(score/sum(score) over (),4) "份額(%)"
from students;

--4、LAG(COL,n,default)、LEAD(OL,n,default) --取前後邊N條數據

select id,lag(score,1,0) over(order by id) lg,score from students;

select id,lead(score,1,0) over(order by id) lg,score from students;

--5、FIRST_VALUE()、LAST_VALUE()

select id,first_value(score) over(order by id) fv,score from students;

select id,last_value(score) over(order by id) fv,score from students;

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 集群結構 特點: 1 所有redis節點(包括主和從)彼此互聯(兩兩通信),底層使用內部的二進位傳輸協議,優化傳輸速度;(所有功能特點的基礎) 2 集群中也有主從,也有高可用的邏輯,但是沒有哨兵進程,整合到主節點的功能里了;集群中的事件被主節點(大部分主節點);通過主節點的過半選舉實現哨兵以前的邏輯 ...
  • 我們經常在linux要查找某個文件,但不知道放在哪裡了,可以使用下麵的一些命令來搜索: which 查看可執行文件的位置。 whereis 查看文件的位置。 locate 配合資料庫查看文件位置。 find 實際搜尋硬碟查詢文件名稱。 which命令的作用是,在PATH變數指定的路徑中,搜索某個系統 ...
  • 第一部分 ES安裝環境的準備和初始化 現在交心的版本Elasticsearch 5.6.3 官方建議安裝Oracle的JDK8,安裝前先檢查機器是否已安裝JDK。 Step 1 檢查環境機器是否已安裝JDK rpm -qa | grep -E '^open[jre|jdk]|j[re|dk]' 如果 ...
  • SQL Server 資料庫中表一旦創建,我們不建議擅自調整列的順序,特別是對應的應用系統已經上線,因為部分開發人員,不一定在代碼中指明瞭列名。表是否可以調整列的順序,其實可以自主設置,我們建議在安裝後設置為禁止。 那麼,如果確實需要調整某一列的順序,我們是怎麼操作的呢? 下麵,我們就要演示一下怎麼 ...
  • 好的表結構分的比較細緻,個人理解大概主要分為主表、明細、歷史記錄表、中間表,輔助表結構應該分為:類型表、狀態表、統計表、統計明細表等。為了一個功能加那麼多表實在是多餘,如果寫一個非常複雜的業務邏輯還是很有必要的,因為要做到物帳聯動。這可能不是一個明智的選擇,還有一種方案是儘可能的壓縮表結構,少分一些 ...
  • 作者:依樂祝 原文地址:https://www.cnblogs.com/yilezhu/p/9941208.html 作者:大石頭 時間:2018 11 10 晚上20:00 地點:釘釘群(組織代碼BKMV7685)QQ群:1600800 內容:Redis基本使用及百億數據量中的使用技巧分享 記錄人 ...
  • Greenplum支持原有主機擴展Segment個數、新增主機、和混合擴展 本文以在已有機器上擴展節點為例 1、可按照hostname:address:port:fselocation:dbid:content:preferred_role:replication_port來配置擴展文件 2、執行命 ...
  • 9. 查詢備份還原資料庫的進度。 select command ,percent_complete ,est_time_to_go=convert(varchar,(estimated_completion_time/3600000))+' hour, ' +convert(varchar,(est ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...