over在聚合函數(shù)中的使用:
一般格式:
聚合函數(shù)名(列) over(選項(xiàng))
over必須與聚合函數(shù)或排序函數(shù)一起使用娇哆,聚合函數(shù)為:
sum(),max(),min(),count(),avg()
排序函數(shù)為:
rank(),row_number(),dense_rank(),ntile()
over表示把函數(shù)當(dāng)成開窗函數(shù)而不是聚合函數(shù)涣楷,SQL標(biāo)準(zhǔn)允許將所有聚合函數(shù)用做開窗函數(shù),使用over關(guān)鍵字來區(qū)分這兩種用法盖桥。
開窗函數(shù)不需要使用group by就可以對數(shù)據(jù)進(jìn)行分組浊洞,就可以同時(shí)返回基礎(chǔ)行的列和聚合列狠裹。
開窗函數(shù)sum(*) over()病蛉,對于查詢結(jié)果的每一行都返回所有符合條件的行的條數(shù)调违,over關(guān)鍵字后的括號中還經(jīng)常添加選項(xiàng)來改變進(jìn)行聚合運(yùn)算的窗口范圍窟哺,如果over關(guān)鍵字后的括號中選項(xiàng)為空,則開窗函數(shù)會對結(jié)果集中的所有行進(jìn)行聚合運(yùn)算翰萨。
常用格式:
sum(*) over(partition by A order by B)
partition by:進(jìn)行分組脏答,得到對應(yīng)組內(nèi)的所有求和值
order by:按照B進(jìn)行排序糕殉,得到對應(yīng)組內(nèi)的累計(jì)求和值(如果B為id,兩個(gè)id相同亩鬼,則這兩個(gè)id返回的sum那一列是相同的聚合值,是累計(jì)到最后一個(gè)id對應(yīng)值的和--下面的例子會詳細(xì)說明)
order by 字段名 rows|range between 邊界規(guī)則1 and 邊界規(guī)則2
rows:表示按照行的范圍進(jìn)行范圍的定位
range:表示按照取值的范圍進(jìn)行范圍的定位
這兩種不同的定位方式主要用來處理并列排序的情況(見下面的例子)
邊界規(guī)則的可取值為:
current row--當(dāng)前行
n preceding--前n行
unbounded preceding--一直到第一條記錄
n following--后n行
unbounded following--一直到最后一條記錄
'range/rows between 邊界規(guī)則1 and 邊界規(guī)則2':用來定位聚合計(jì)算范圍阿蝶,被稱為定位框架雳锋。
eg:
1、建表
CREATE TABLE over2 (
FName VARCHAR(20),FCity VARCHAR(20),FAge INT,FSalary INT);
2羡洁、插入數(shù)據(jù)
INSERT INTO over2(FName,FCity,FAge,FSalary) VALUES
('Tom','BeiJing',20,3000),('Tim','ChengDu',21,4000),('Jim','BeiJing',22,3500),('Lily','London',21,2000),('John','NewYork',22,1000),('YaoMing','BeiJing',20,3000),('Swing','London',22,2000),('Guo','NewYork',20,2800),('YuQian','BeiJing',24,8000),('Ketty','London',25,8500),('Kitty','ChengDu',25,3000),('Merry','BeiJing',23,3500),
('Smith','ChengDu',30,3000),('Bill','BeiJing',25,2000),('Jerry','NewYork',24,3300);
3玷过、關(guān)于partition by
(1)所屬城市的人員數(shù)-按城市進(jìn)行分組聚合
SELECT
*,
count( * ) over ( PARTITION BY Fcity )
FROM
over2;
(2)顯示每一個(gè)人員的信息、所屬城市的人員數(shù)以及同齡人的人數(shù)
SELECT
*,
count( * ) over ( PARTITION BY Fcity ) '所屬城市人員數(shù)',
count( * ) over ( PARTITION BY FAge ) '所屬同齡人員數(shù)'
FROM
over2;
在同一個(gè)SELECT語句中可以同時(shí)使用多個(gè)開窗函數(shù)筑煮,而且這些開窗函數(shù)并不會相互干擾辛蚊。
4、關(guān)于order by的詳解:
(1)查詢從第一行到當(dāng)前行的的工資總和
select FName,Fcity,FAge,FSalary,
sum(FSalary) over(order by FSalary rows between unbounded preceding and current row) '到當(dāng)前行工資求和'
from over2;
(2)將上面的row換成range
select FName,Fcity,FAge,FSalary,
sum(FSalary) over(order by FSalary range between unbounded preceding and current row) '到當(dāng)前行工資求和'
from over2;
結(jié)果和(1)的區(qū)別體現(xiàn)在紅框和黃框部分真仲,按照FSalary進(jìn)行排序袋马,row-按照行的范圍進(jìn)行范圍定位,所以每一行后面對應(yīng)的‘到當(dāng)前行工資求和’都不一樣秸应,都嚴(yán)格的是第一行到當(dāng)前行的累計(jì)和虑凛;range-按照取值的范圍進(jìn)行范圍定位,雖然定位框架的語法仍然是從第一行到當(dāng)前行的累計(jì)和软啼,但是由于取值的范圍:等于2000元的工資有3人桑谍,所以計(jì)算的累計(jì)為從第一條到2000元工資的最后一個(gè)人,寫在每個(gè)2000元工資的人的后面都是7000祸挪。
(3)將(2)中的定位框架省略
range between unbounded preceding and current row
上述框架是開窗函數(shù)中最常用的定位框架锣披,如果是這種框架的話,可以省略上述定位框架部分
SELECT
FName,
Fcity,
FAge,
FSalary,
sum( FSalary ) over ( ORDER BY FSalary ) '到當(dāng)前行工資求和'
FROM
over2;
得到的結(jié)果和(2)的結(jié)果一樣贿条。
(4)將上面的sum()換成count()雹仿,計(jì)算工資排名
按照salary進(jìn)行排序,然后計(jì)算從第一行(unbounded preceding)到當(dāng)前行(current row)的人員的個(gè)數(shù)闪唆,相當(dāng)于計(jì)算人員的的工資水平排名盅粪。
Question:
怎么讓工資為2000元的排名都為2?--見后面排序函數(shù)的rank()和dence_rank()
5悄蕾、關(guān)于over(partition by A order by B)
select FName,Fcity,FAge,FSalary,
sum(FSalary) over(partition by FAge order by FSalary) '同齡人的累計(jì)工資'
from over2;
over在排序函數(shù)中的使用:
一般格式:
排序函數(shù)(列) over(選項(xiàng))
排序函數(shù)為:
rank(),dense_rank(),row_number(),ntile(),lead(),lag()
1票顾、rank(),dense_rank(),row_number()的區(qū)別
select FName,Fcity,FAge,FSalary,
rank() over(order by FSalary desc) f_rank,
dense_rank() over(order by FSalary desc) f_dense_rank,
row_number() over(order by FSalary desc) f_row_number
from over2;
rank()與dense_rank()的區(qū)別:
兩者都是計(jì)算一組數(shù)值中的排序值础浮,
但是在有并列關(guān)系時(shí),dence_rank中相關(guān)等級不會跳過奠骄,rank則跳過豆同。
rank() 是跳躍排序,有兩個(gè)第二名時(shí)接下來就是第四名(同樣是在各個(gè)分組內(nèi))
dense_rank()是連續(xù)排序含鳞,有兩個(gè)第二名時(shí)仍然跟著第三名影锈。
row_number():
row_number over(partition by A order by B)
根據(jù)A分組,在分組內(nèi)根據(jù)B排序蝉绷,且得出來的值是每組內(nèi)部排序后的順序編號(組內(nèi)連續(xù)的唯一的)
其主要是‘行’的信息鸭廷,并沒有排名。row_number()必須與order by一起使用熔吗,
多用于分頁查詢辆床,比如查詢10-100個(gè)學(xué)生。
select * from
(select *,row_number() over(order by FSalary DESC) paixu from over2) r
where r.paixu between 6 and 10;
2桅狠、ntile(x)--平均分區(qū)函數(shù)
select FName,Fcity,FAge,FSalary,
ntile(3) over(order by FSalary) 分區(qū) from over2;
3讼载、lag() over(partition by A order by B)
lead() over(partition by A order by B)
lag和lead中有三個(gè)參數(shù),lag('列名',offset,'超出記錄窗口時(shí)的默認(rèn)值')
lag和lead可以獲取中跌,按一定順序B排列的當(dāng)前行的上下相鄰若干offset的莫隔行的某個(gè)列咨堤。
lag()是向前,lead()是向后漩符。
select FName,Fcity,FAge,FSalary,
lag(FSalary,1,'超出') over(order by FSalary DESC) f_lag向前,
lead(FSalary,1,'超出') over(order by FSalary DESC) f_lead向后
from over2;