Oracle開發(fā)之分析函數(shù)(Top/Bottom N、First/Last、NTile)
一、帶空值的排列:
在前面《Oracle開發(fā)之分析函數(shù)(Rank、Dense_rank、row_number)》一文中,我們已經(jīng)知道了如何為一批記錄進行全排列、分組排列。假如被排列的數(shù)據(jù)中含有空值呢?
sum(customer_sales) cust_sales,
sum(sum(customer_sales)) over(partition by region_id) ran_total,
rank() over(partition by region_id
order by sum(customer_sales) desc) rank
from user_order
group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_SALES RAN_TOTAL RANK
---------- ----------- ---------- ---------- ----------
10 31 6238901 1
10 26 1808949 6238901 2
10 27 1322747 6238901 3
10 30 1216858 6238901 4
10 28 986964 6238901 5
10 29 903383 6238901 6
我們看到這里有一條記錄的CUST_TOTAL字段值為NULL,但居然排在第一名了!顯然這不符合情理。所以我們重新調(diào)整完善一下我們的排名策略,看看下面的語句:
sum(customer_sales) cust_total,
sum(sum(customer_sales)) over(partition by region_id) reg_total,
rank() over(partition by region_id
order by sum(customer_sales) desc NULLS LAST) rank
from user_order
group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_TOTAL REG_TOTAL RANK
---------- ----------- ---------- ---------- ----------
10 26 1808949 6238901 1
10 27 1322747 6238901 2
10 30 1216858 6238901 3
10 28 986964 6238901 4
10 29 903383 6238901 5
10 31 6238901 6
綠色高亮處,NULLS LAST/FIRST告訴Oracle讓空值排名最后后第一。
注意是NULLS,不是NULL。
二、Top/Bottom N查詢:
在日常的工作生產(chǎn)中,我們經(jīng)常碰到這樣的查詢:找出排名前5位的訂單客戶、找出排名前10位的銷售人員等等?,F(xiàn)在這個對我們來說已經(jīng)是很簡單的問題了。下面我們用一個實際的例子來演示:
【1】找出所有訂單總額排名前3的大客戶:
from (select region_id,
customer_id,
sum(customer_sales) cust_total,
rank() over(order by sum(customer_sales) desc NULLS LAST) rank
from user_order
group by region_id, customer_id)
where rank <= 3;
REGION_ID CUSTOMER_ID CUST_TOTAL RANK
---------- ----------- ---------- ----------
9 25 2232703 1
8 17 1944281 2
7 14 1929774 3
SQL>
【2】找出每個區(qū)域訂單總額排名前3的大客戶:
from (select region_id,
customer_id,
sum(customer_sales) cust_total,
sum(sum(customer_sales)) over(partition by region_id) reg_total,
rank() over(partition by region_id
order by sum(customer_sales) desc NULLS LAST) rank
from user_order
group by region_id, customer_id)
where rank <= 3;
REGION_ID CUSTOMER_ID CUST_TOTAL REG_TOTAL RANK
---------- ----------- ---------- ---------- ----------
5 4 1878275 5585641 1
5 2 1224992 5585641 2
5 5 1169926 5585641 3
6 6 1788836 6307766 1
6 9 1208959 6307766 2
6 10 1196748 6307766 3
7 14 1929774 6868495 1
7 13 1310434 6868495 2
7 15 1255591 6868495 3
8 17 1944281 6854731 1
8 20 1413722 6854731 2
8 18 1253840 6854731 3
9 25 2232703 6739374 1
9 23 1224992 6739374 2
9 24 1224992 6739374 2
10 26 1808949 6238901 1
10 27 1322747 6238901 2
10 30 1216858 6238901 3
18 rows selected.
三、First/Last排名查詢:
想象一下下面的情形:找出訂單總額最多、最少的客戶。按照前面我們學到的知識,這個至少需要2個查詢。第一個查詢按照訂單總額降序排列以期拿到第一名,第二個查詢按照訂單總額升序排列以期拿到最后一名。是不是很煩?因為Rank函數(shù)只告訴我們排名的結果,卻無法自動替我們從中篩選結果。
幸好Oracle為我們在排列函數(shù)之外提供了兩個額外的函數(shù):first、last函數(shù),專門用來解決這種問題。還是用實例說話:
keep (dense_rank first order by sum(customer_sales) desc) first,
min(customer_id)
keep (dense_rank last order by sum(customer_sales) desc) last
from user_order
group by customer_id;
FIRST LAST
---------- ----------
31 1
這里有幾個看起來比較疑惑的地方:
①為什么這里要用min函數(shù)
②Keep這個東西是干什么的
③fist/last是干什么的
④dense_rank和dense_rank()有什么不同,能換成rank嗎?
首先解答一下第一個問題:min函數(shù)的作用是用于當存在多個First/Last情況下保證返回唯一的記錄。假如我們?nèi)サ魰惺裁礃拥暮蠊兀?br />
keep (dense_rank last order by sum(customer_sales) desc) last
from user_order
group by customer_id;
select keep (dense_rank first order by sum(customer_sales) desc) first,
*
ERROR at line 1:
ORA-00907: missing right parenthesis
接下來看看第2個問題:keep是干什么用的?從上面的結果我們已經(jīng)知道Oracle對排名的結果只“保留”2條數(shù)據(jù),這就是keep的作用。告訴Oracle只保留符合keep條件的記錄。
那么什么才是符合條件的記錄呢?這就是第3個問題了。dense_rank是告訴Oracle排列的策略,first/last則告訴最終篩選的條件。
第4個問題:如果我們把dense_rank換成rank呢?
keep(rank first order by sum(customer_sales) desc) first,
min(region_id)
keep(rank last order by sum(customer_sales) desc) last
from user_order
group by region_id;
select min(region_id)
*
ERROR at line 1:
ORA-02000: missing DENSE_RANK
四、按層次查詢:
現(xiàn)在我們已經(jīng)見識了如何通過Oracle的分析函數(shù)來獲取Top/Bottom N,第一個,最后一個記錄。有時我們會收到類似下面這樣的需求:找出訂單總額排名前1/5的客戶。
很熟悉是不?我們馬上會想到第二點中提到的方法,可是rank函數(shù)只為我們做好了排名,并不知道每個排名在總排名中的相對位置,這時候就引入了另外一個分析函數(shù)NTile,下面我們就以上面的需求為例來講解一下:
customer_id,
ntile(5) over(order by sum(customer_sales) desc) til
from user_order
group by region_id, customer_id;
REGION_ID CUSTOMER_ID TILE
---------- ----------- ----------
10 31 1
9 25 1
10 26 1
6 6 1
8 18 2
5 2 2
9 23 3
6 9 3
7 11 3
5 3 4
6 8 4
8 16 4
6 7 5
10 29 5
5 1 5
Ntil函數(shù)為各個記錄在記錄集中的排名計算比例,我們看到所有的記錄被分成5個等級,那么假如我們只需要前1/5的記錄則只需要截取TILE的值為1的記錄就可以了。假如我們需要排名前25%的記錄(也就是1/4)那么我們只需要設置ntile(4)就可以了。
以上就是Oracle中前幾名、后幾名、最多、最少以及按層次查詢的全部內(nèi)容,希望能給大家一個參考,也希望大家多多支持腳本之家。
- Oracle中的分析函數(shù)匯總
- Oracle數(shù)據(jù)庫分析函數(shù)用法
- Oracle百分比分析函數(shù)RATIO_TO_REPORT() OVER()實例詳解
- oracle常用分析函數(shù)與聚合函數(shù)的用法
- 常用Oracle分析函數(shù)大全
- Oracle開發(fā)之分析函數(shù)總結
- Oracle開發(fā)之分析函數(shù)(Rank, Dense_rank, row_number)
- Oracle開發(fā)之分析函數(shù)簡介Over用法
- 深入探討:oracle中row_number() over()分析函數(shù)用法
- Oracle 分析函數(shù)RANK(),ROW_NUMBER(),LAG()等的使用方法
- Oracle分析函數(shù)用法詳解
相關文章
oracle表空間不足ORA-01653的問題:?unable?to?extend?table
這篇文章主要介紹了oracle表空間不足ORA-01653:?unable?to?extend?table的問題?,出現(xiàn)這種表空間不足的問題一般有兩種情況:一種是表空間的自動擴展功能沒有打開,另一種確實是表空間確實不夠用了,已經(jīng)達到了擴展的極限,本文給大家分享解決方法,需要的朋友參考下2022-08-08ORACLE?ORA-01653:?unable?to?extend?table?的錯誤處理方案(oracl
這篇文章主要介紹了ORACLE?ORA-01653:?unable?to?extend?table?的錯誤處理方案,本文通過具體步驟給大家分享解決方案,需要的朋友可以參考下2022-08-08Oracle安裝TNS_ADMIN環(huán)境變量設置參考
這篇文章主要為大家介紹了Oracle安裝過程中關于TNS_ADMIN環(huán)境變量設置的參考,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-10-10inner join和left join之間的區(qū)別詳解
這篇文章主要給大家介紹了關于inner join和left join之間區(qū)別的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01在OracleE數(shù)據(jù)庫的字段上建立索引的方法
在OracleE數(shù)據(jù)庫的字段上建立索引的方法...2007-04-04