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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...