日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

开窗函数的意义与用法

發布時間:2023/12/3 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 开窗函数的意义与用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

開窗函數——排序函數

開窗函數與其他函數的區別是,它不是關聯其他表查詢,而是在一張表內根據我們的想法自定義的規則分組后對我們組內的數據進行檢索和計算。我們自定義的規則所分的組,就如同整張表的一個個小窗口,因此我們開出一個個小窗口并對這些小窗口進行的操作就叫做開窗函數。
開窗函數分為排序函數和聚合函數。

一、排序函數:

1.三個排序函數

句型:row_number()的排序函數

order_func OVER([PARTITION BY expression] ORDER BY clase)

其中,order_func是指排序函數,包括:
row_number(),rank(),dense_rank(),ntile();
他們會為每一行返回一個序值。
PARTITION BY 是我們自定義的分組策略,如果不用,該函數會把其余select 語句包括where、having、group by的運行結果做為窗口進行排序;ORDER BY 是排序的方法,即每個窗口內根據哪個字段排序,不能缺省。
例如:我們需要對一個包含4個班級的16個同學的成績表進行以班為單位的排序,我們可以這樣排序:

select st_name,st_class,st_score,row_number() over(partition by st_class order by score)  as '名次'
from score_tab;

但有時候我們的業務需求我們排序,但不以表中的字段排。而我們又不能沒有ORDER BY語句,我們應該怎么辦呢?是的,開發者也考慮到了:

select st_name,st_class,st_score,row_number() over(partition by st_class order by (select 0))  as '名次'
from score_tab;

當然,這并不是所有sql家族成員都是這么設計的,比如hive的方法就略有不同:

select st_name,st_class,st_score,row_number() over(partition by st_class order by 0)  as '序值'
from score_tab;

直接用0,并不用select 0;
當然,這種排序也是有弊端的,就拿我們的學習成績為例,假如同一個窗口內的兩個同學分數相同,我們按這種方法排,可能他們一個是第二名,一個是第三名,這樣對孩子就太不公平了。于是,我們又有了另外兩種排序方式:
rank()和dense_rank()
三者的區別是:

row_number() 對窗口每一行記錄輸出一個序值,同一窗口不會有重復的充值,無論排序字段值是否相等,都是1,2,3,4;
rank() 對窗口內每一行記錄輸出一個序值,字段值相同的,則輸出相同序值,下一充值為非密集排序,如1,2,2,4;
dense_rank() 對窗口內每一行記錄輸出一個充值,字段值相同的,則輸出相同序值,下一序值為密集排序,如:1,2,2,3;

2.數據均分分組函數–NTILE()

NTILE()的功能是進行均分分組,其參數是我們要分組的數量,比如,我們把學生平均分為四組,

select st_name,, st_class,,st_score,NTILE(4) OVER(ORDER BY st_score) as '分組'
from score_tab;

結果是按照成績排列為1,2,3,4組,部分數據如下:

st_name st_class st_score 分組
a 1 68 1
c 4 69 1
r 3 72 1
d 4 85 1

如果我們按班級為單位,把每一個班的成績平均分為高、下兩種評級,則:

select st_name,, st_class,,st_score,CASE NTILE(2) OVER(PARTITION BY st_class ORDER BY st_score) when 1 then '低'when 1 then '高'END AS ‘level’
from score_tab;
st_name st_class st_score level
p 4 69
g 4 75
e 4 87
j 4 92

總結:

一般我們在使用排序函數的時候,我們不會同時使用distinct,因為我們在給記錄進行排序時,一般會忽略同值記錄,事實上我們執行如下語法,其中的distinct并沒有起作用,不會去重,只是增加了資源的開銷:

SELECT DISTINCT st_score,ROW_NUMBER() OVER(PARTITION BY st_class ORDER BY st_score) AS '排名'
FROM score_tab;

如果我們業務真實需要去重后再編序值,請用過濾條件GROUP BY,如:

SELECT st_score,ROW_NUMBER() OVER(PARTITION BY st_class ORDER BY st_score) AS '排名'
FROM score_tab
GROUP BY st_score;

相關:替代方案–子查詢

在開窗函數沒有發布之前,我們進行窗口操作都是使用子查詢進行的,其原理為:先查出該組內比當前成績低的個數,再加上1,就是該學生在該組的序值,如:

select st_name,st_class,st_score--開窗函數方式,row_number() over(partition by st_class order by score) as '開窗序值名次'--子查詢(SELECT COUNT(1)+1 FORM st_score s2WHERE s2.st_class=a1.st_class AND s2.st_score<s1.st_score) as 子查詢名次
from score_tab s1;--如果是密集排序,我們只需把count()的參數改為排序字段即可去重,如
select st_name,st_class,st_score--開窗函數方式,row_number() over(partition by st_class order by score) as '開窗序值名次'--子查詢(SELECT COUNT(st_score)+1 FORM st_score s2WHERE s2.st_class=a1.st_class AND s2.st_score<s1.st_score) as 子查詢名次
from score_tab s1;

總結

以上是生活随笔為你收集整理的开窗函数的意义与用法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。