开窗函数

over在聚合函数中的使用:
一般格式:
聚合函数名(列) over(选项)
over必须与聚合函数或排序函数一起使用,聚合函数为:
sum(),max(),min(),count(),avg()
排序函数为:
rank(),row_number(),dense_rank(),ntile()
over表示把函数当成开窗函数而不是聚合函数,SQL标准允许将所有聚合函数用做开窗函数,使用over关键字来区分这两种用法。
开窗函数不需要使用group by就可以对数据进行分组,就可以同时返回基础行的列和聚合列。

开窗函数sum(*) over(),对于查询结果的每一行都返回所有符合条件的行的条数,over关键字后的括号中还经常添加选项来改变进行聚合运算的窗口范围,如果over关键字后的括号中选项为空,则开窗函数会对结果集中的所有行进行聚合运算。

常用格式:
sum(*) over(partition by A order by B)
partition by:进行分组,得到对应组内的所有求和值
order by:按照B进行排序,得到对应组内的累计求和值(如果B为id,两个id相同,则这两个id返回的sum那一列是相同的聚合值,是累计到最后一个id对应值的和--下面的例子会详细说明)

order by 字段名 rows|range between 边界规则1 and 边界规则2
rows:表示按照行的范围进行范围的定位
range:表示按照取值的范围进行范围的定位
这两种不同的定位方式主要用来处理并列排序的情况(见下面的例子)
边界规则的可取值为:
current row--当前行
n preceding--前n行
unbounded preceding--一直到第一条记录
n following--后n行
unbounded following--一直到最后一条记录
'range/rows between 边界规则1 and 边界规则2':用来定位聚合计算范围,被称为定位框架。

eg:
1、建表

CREATE TABLE over2 (
FName VARCHAR(20),FCity VARCHAR(20),FAge INT,FSalary INT);

2、插入数据

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、关于partition by
(1)所属城市的人员数-按城市进行分组聚合

SELECT
    *,
    count( * ) over ( PARTITION BY Fcity ) 
FROM
    over2;
image.png

(2)显示每一个人员的信息、所属城市的人员数以及同龄人的人数

SELECT
    *,
    count( * ) over ( PARTITION BY Fcity ) '所属城市人员数',
    count( * ) over ( PARTITION BY FAge ) '所属同龄人员数'
FROM
    over2;
image.png

在同一个SELECT语句中可以同时使用多个开窗函数,而且这些开窗函数并不会相互干扰。
4、关于order by的详解:
(1)查询从第一行到当前行的的工资总和

select FName,Fcity,FAge,FSalary,
             sum(FSalary) over(order by FSalary rows between unbounded preceding and current row) '到当前行工资求和'
from over2;
image.png

(2)将上面的row换成range

select FName,Fcity,FAge,FSalary,
             sum(FSalary) over(order by FSalary range between unbounded preceding and current row) '到当前行工资求和'
from over2;
image.png

结果和(1)的区别体现在红框和黄框部分,按照FSalary进行排序,row-按照行的范围进行范围定位,所以每一行后面对应的‘到当前行工资求和’都不一样,都严格的是第一行到当前行的累计和;range-按照取值的范围进行范围定位,虽然定位框架的语法仍然是从第一行到当前行的累计和,但是由于取值的范围:等于2000元的工资有3人,所以计算的累计为从第一条到2000元工资的最后一个人,写在每个2000元工资的人的后面都是7000。
(3)将(2)中的定位框架省略

range between unbounded preceding and current row

上述框架是开窗函数中最常用的定位框架,如果是这种框架的话,可以省略上述定位框架部分

SELECT
    FName,
    Fcity,
    FAge,
    FSalary,
    sum( FSalary ) over ( ORDER BY FSalary ) '到当前行工资求和' 
FROM
    over2;

得到的结果和(2)的结果一样。
(4)将上面的sum()换成count(),计算工资排名


image.png

按照salary进行排序,然后计算从第一行(unbounded preceding)到当前行(current row)的人员的个数,相当于计算人员的的工资水平排名。
Question:
怎么让工资为2000元的排名都为2?--见后面排序函数的rank()和dence_rank()
5、关于over(partition by A order by B)

select FName,Fcity,FAge,FSalary,
            sum(FSalary) over(partition by FAge order by FSalary) '同龄人的累计工资'
from over2;
image.png

over在排序函数中的使用:
一般格式:
排序函数(列) over(选项)
排序函数为:
rank(),dense_rank(),row_number(),ntile(),lead(),lag()
1、rank(),dense_rank(),row_number()的区别

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;
image.png

rank()与dense_rank()的区别:
两者都是计算一组数值中的排序值,
但是在有并列关系时,dence_rank中相关等级不会跳过,rank则跳过。
rank() 是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内)
dense_rank()是连续排序,有两个第二名时仍然跟着第三名。
row_number():
row_number over(partition by A order by B)
根据A分组,在分组内根据B排序,且得出来的值是每组内部排序后的顺序编号(组内连续的唯一的)
其主要是‘行’的信息,并没有排名。row_number()必须与order by一起使用,
多用于分页查询,比如查询10-100个学生。

select * from
(select *,row_number() over(order by FSalary DESC) paixu from over2) r
where r.paixu between 6 and 10;
image.png

2、ntile(x)--平均分区函数

select FName,Fcity,FAge,FSalary,
             ntile(3) over(order by FSalary) 分区 from over2;
image.png

3、lag() over(partition by A order by B)
lead() over(partition by A order by B)
lag和lead中有三个参数,lag('列名',offset,'超出记录窗口时的默认值')
lag和lead可以获取,按一定顺序B排列的当前行的上下相邻若干offset的莫隔行的某个列。
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;
image.png

参考https://www.cnblogs.com/lihaoyang/p/6756956.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350