【SQL】窗口函数及其他进阶用法

一个支持SQL online的在线编译器😄
https://www.jdoodle.com/execute-sql-online/

基本用法

执行顺序:哪里分组有订单 Where, Group By, Having, Order by


窗口函数

定义

窗口函数:SQL语句中OVER子句,OVER()括号里的内容就是窗口函数的作用域,窗口函数中的元素,常见的有三类:分区、排序、框架

1)分区
PARTITION BY COL1 [ORDER BY COL2]
2)排序
3)框架:是在一个分区内进行进一步限制的筛选器
FIRST_VALUE
LAST_VALUE

支持窗口函数的查询元素:SELECT、ORDER BY

类别
1)排名:ROW_NUMBER( )、RANK( )、DENSE_RANK( )

2)分布函数
PERCENT_RANK(百分位排名)、CUME_DIST(累计分布)

3)偏移函数
FIRST_VALUE、LAST_VALUE

案例

表格如下:

create table SC(SId varchar(10),CId varchar(10),score decimal(18,1));
insert into SC values('01' , 'mat' , 80);
insert into SC values('01' , 'pai' , 90);
insert into SC values('01' , 'eng' , 99);
insert into SC values('02' , 'mat' , 70);
insert into SC values('02' , 'pai' , 60);
insert into SC values('02' , 'eng' , 80);
insert into SC values('03' , 'mat' , 80);
insert into SC values('03' , 'pai' , 80);
insert into SC values('03' , 'eng' , 80);
insert into SC values('04' , 'mat' , 50);
insert into SC values('04' , 'pai' , 30);
insert into SC values('04' , 'eng' , 20);
insert into SC values('05' , 'mat' , 76);
insert into SC values('05' , 'pai' , 87);
insert into SC values('06' , 'mat' , 31);
insert into SC values('06' , 'eng' , 34);
insert into SC values('07' , 'pai' , 89);
insert into SC values('07' , 'eng' , 98);

Output
在这里插入图片描述

1. 组内排序

  • RANK( )
    用法:最常用的方式,如果有两个并列第一,那么只有第三名,无第二名
    语法:rank() over(partition by 分类组别 order by 排序列 desc) rank
    可以把这个语句视为新生成一个变量
select SId,CId,rank() 
	over(partition by CId order by score desc) rank 
	from SC;

Output
在这里插入图片描述

  • DENSE_RANK( )
    用法:如果有两个并列第一,仍然有第二名
    语法:dense_rank() over(partition by 分类组别 order by 排序列 desc) rank
    可以把这个语句视为新生成一个变量
select SId,CId,dense_rank() 
	over(partition by CId order by score desc) rank 
	from SC;

Output
在这里插入图片描述

  • ROW_NUMBER( )
    用法:不允许并列,如果有两个并列第一,那么其中一个是第一,另一个是第二
    语法:row_number() over(partition by 分类组别 order by 排序列 desc) rank
    可以把这个语句视为新生成一个变量
select SId,CId,score,ROW_NUMBER() 
	over(partition by CId order by score desc) rank 
	from SC;

Output
在这里插入图片描述

2. 组内Top n, Bottom n

思路:就是组内排序外面再加一层查询,easy!

  • 每组的top3
select new_SC.*,new_SC.rn 
	from (select SId,CId,score,row_number() 
		over(partition by CId order by score desc) rn 
		from SC) as new_SC 
	where new_SC.rn < 4 ;

Output
在这里插入图片描述

  • 每组的bottom3
select new_SC.*,new_SC.rn 
	from (select SId,CId,score,row_number() 
		over(partition by CId order by score asc) rn 
		from SC) as new_SC 
	where new_SC.rn < 4 ;

Output
在这里插入图片描述

3. 把组内不同行转列

案例1:

select SId, 
	max(case CId when 'eng' then score else 0 end) eng, 
	max(case CId when 'mat' then score else 0 end) mat,
	max(case CId when 'pai' then score else 0 end) pai 
	from SC 
	group by SId;

在这里插入图片描述

案例2和3的数据集

create table SC(SId varchar(10),CId varchar(10),score decimal(18,1));
insert into SC values('01' , 'mat' , 80);
insert into SC values('01' , 'pai' , 90);
insert into SC values('01' , 'eng' , 99);
insert into SC values('02' , 'mat' , 70);
insert into SC values('02' , 'pai' , 60);
insert into SC values('02' , 'eng' , 80);
insert into SC values('03' , 'mat' , 80);
insert into SC values('03' , 'pai' , 80);
insert into SC values('03' , 'eng' , 80);
insert into SC values('04' , 'mat' , 50);
insert into SC values('04' , 'pai' , 30);
insert into SC values('04' , 'eng' , 20);
insert into SC values('05' , 'mat' , 76);
insert into SC values('05' , 'pai' , 87);
insert into SC values('06' , 'mat' , 31);
insert into SC values('06' , 'eng' , 34);
insert into SC values('07' , 'pai' , 89);
insert into SC values('07' , 'eng' , 98);
insert into SC values('08' , 'mat' , 99);
insert into SC values('08' , 'eng' , 100);
insert into SC values('09' , 'eng' , 100);

Output
在这里插入图片描述

案例2
查询只选了英语课的学生

select * from SC 
	group by SId
	having count(CId) = sum(case when CId = 'eng' then 1 else 0 end);

案例3
查询选课内容和06号学生一样的其他学生信息

select t1.SId,t1.allCId from 

    (select SId, eng||mat||pai as allCId from 
        (select SId,
            max(case when CId = 'eng' then 1 else 0 end) eng,
            max(case when CId = 'mat' then 1 else 0 end) mat,
            max(case when CId = 'pai' then 1  else 0 end) pai
            from SC
        group by SId) 
    ) t1,  --第一张表用于生产新字段
    
    (select allCId from
        (select SId, eng||mat||pai as allCId from 
            (select SId,
                max(case when CId = 'eng' then 1 else 0 end) eng,
                max(case when CId = 'mat' then 1 else 0 end) mat,
                max(case when CId = 'pai' then 1  else 0 end) pai
                from SC
                group by SId) 
            ) where SId = '06'
    )as t2  --第二张表用于找到学号06学生的值
    
where t1.allCId = t2.allCId;

Output
在这里插入图片描述

4. 随机取数

从SC表格中随机取出5个数

select * from SC order by Random() limit 5;

在这里插入图片描述

https://bbs.csdn.net/topics/392012376

随机抽取n%的数据

5. 求众数、中位数(组内)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值