一、什么是窗口函数

1.什么是窗口函数?

窗口函数,也叫OLAP函数(Online Analytical Processing,联机分析处理),可以对数据库数据进行实时分析处理。

窗口函数的基本语法如下:

<窗口函数> over ( partition by <用于分组的列名>order by <用于排序的列名>)

<窗口函数>的位置可以放以下两种函数:

1) 专用窗口函数,如rank,dense_rank,row_number等

2) 聚合函数,如sum,avg,count,max,min等

因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中。

2.窗口函数有什么用?

在日常工作中,经常会遇到需要在每组内排名,比如下面的业务需求:

1) 经典排名问题:每个部门按业绩来排名

2) 经典top N问题:找出每个部门排名前N的员工进行奖励

3) 在每个组里比较的问题:查找每个组里大于平均值的数据

面对这类需求,就需要使用SQL的高级功能窗口函数了。

二、如何使用窗口函数

1.以专用窗口函数rank为例介绍窗口函数的用法

实例:已知班级表(左表)中的内容,现在我们想在每个班级内按成绩排名,得到右表中的结果。

select *,
rank() over (partition by 班级 order by 成绩 desc) as ranking
from 班级表;

2.group by子句具有分组的功能,order by子句具有排序的功能,为什么还要用窗口函数?

因为group by分组汇总后改变了表的行数,一行只有一个类别。而partition by和rank函数不会减少原表中的行数。

例如下面统计每个班级的人数:

3.窗口函数的功能

简单来说,窗口函数具有以下功能:

1)同时具有分组和排序的功能

2)不减少原表的行数

3)语法如下:

<窗口函数> over (partition by <用于分组的列名>order by <用于排序的列名>)

三、其他专用窗口函数

除rank外,专用窗口函数还包括dense_rank,row_number等,下面举个例子来说明这三个专用窗口函数的区别:

select *,
rank() over (order by 成绩 desc) as ranking,
dense_rank() over (order by 成绩 desc) as dese_rank,
row_number() over (order by 成绩 desc) as row_num
from 班级表;

查询结果为:

从查询结果看出:

  • rank函数:这个例子中是5位,5位,5位,8位,也就是如果有并列名次的行,会占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,4。
  • dense_rank函数:这个例子中是5位,5位,5位,6位,也就是如果有并列名次的行,不占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,2。
  • row_number函数:这个例子中是5位,6位,7位,8位,也就是不考虑并列名次的情况。比如前3名是并列的名次,排名是正常的1,2,3,4。

remark:在上述的这三个专用窗口函数中,函数后面的括号不需要任何参数,保持()空着就可以。

案例:面试经典排名问题

下图是班级表中的内容,记录了每个学生所在班级和对应的成绩。

现在需要按成绩来排名,如果两个分数相同,那么排名要是并列的。

select *,
dense_rank() over (order by 成绩 desc) as ranking
from 班级表;

查询结果为:

案例:面试经典top N问题

面试中常见的几类问题:

  • 分组取每组最大值
  • 分组取每组最小值
  • 每组最大的N条(top N)记录

下面我们通过成绩表的例子来给出该类问题的解决方案。

  • 分组取每组最大值

案例:按课程号分组取成绩最大值所在行的数据

select *
from score as a
where 成绩 = ( select max(成绩)  from score as b  where a.课程号 = b.课程号);

  • 分组取每组最小值

案例:按课程号分组取成绩最小值所在行的数据

select *
from score as a
where 成绩 = ( select min(成绩)  from score as b  where a.课程号 = b.课程号);

  • 每组最大的N条记录

案例:下图中的各科成绩表记录了每个学生各科的成绩,如何查找每个学生成绩最高的2个科目?

select *
from (select *,
row_number() over (partition by 姓名 order by 成绩 desc) as ranking
from 各科成绩表) as a
where ranking <= 2;

查询结果为:

四、聚合函数作为窗口函数

聚合窗口函数和专用窗口函数用法完全相同,只需要把聚合函数写在窗口函数的位置即可,但是函数后面的括号里面不能为空,需要指定聚合的列名。

举个例子来说明聚合函数的作用:

select *,
sum(成绩) over (order by 学号) as current_sum,
avg(成绩) over (order by 学号) as current_avg,
count(成绩) over (order by 学号) as current_count,
max(成绩) over (order by 学号) as current_max,
min(成绩) over (order by 学号) as current_min
from 班级表;

查询结果为:

由查询结果可得,聚合窗口函数都是对自身以及自身记录之上的所有数据进行计算。比如学号0005后面的聚合窗口函数结果是:学号0001~0005五人成绩的总和、平均、计数及最大最小值。如果想要知道所有人成绩的总和、平均等聚合结果,看最后一行即可。

这样使用窗口函数有什么用呢?

聚合函数作为窗口函数,可以在每一行的数据里直观的看到截止到本行数据,统计数据是多少,同时可以看出每一行数据对整体统计数据的影响。

案例:如何在每个组里比较?

问题:现有成绩表(表格见前面的例子),查找单科成绩高于该科目平均成绩的学生名单?

方法一:使用关联子查询

select *
from 各科成绩表 as a
where 成绩 > (select avg(成绩) from 各科成绩表 as b where a.科目 = b.科目 group by 科目 );

方法二:使用聚合窗口函数

select *
from (select *,
avg(成绩) over (partition by 科目) as 平均成绩
from 各科成绩表) as a
where 成绩 > 平均成绩;

五、窗口函数的移动平均

举个例子来说明移动平均的概念:

select *,
avg(成绩) over (order by 学号 rows 2 preceding) as current_avg
from 班级表;

查询结果为:

对查询结果进行分析:

通过分析可知,"rows...preceding"是“之前...行”的意思。本例的SQL语句是之前2行,即得到的结果是自身记录及前2行的平均。想要计算当前行与前n行(共n+1行)的平均时,只要调整rows…preceding中间的数字即可。

这样使用窗口函数有什么用呢?

通过preceding关键字可以调整移动平均的作用范围,这一点在以下场景中非常适用:

在公司业绩名单排名中,可以通过移动平均直观地查看到与相邻名次业绩的平均、求和等统计数据。

sql取最大值的那一行_从零学会SQL:SQL高级功能相关推荐

  1. SQL 取空格右边的字符_从零学会SQL,第2关

    [一.基本的查询语句] SQL书写规则:以英文 ; 结尾 不区分关键字的大小写 符号皆为英文 列名不加单引号,不加空格 select <列名1>,<列名2> from < ...

  2. sql取最大值的那一行_SQL高级功能

    1. 什么是窗口函数?(---MySQL 8以上才有该函数---) 1) 窗口函数有什么用? 日常工作中,时常遇到需要在每组内排名,比如: 1.1 排名问题:每个部门按业绩排名 1.2 TopN问题: ...

  3. SQL取最大值编码(自动编码)

    SQL取最大值编码(自动编码) 用途 : 使用SQL语法做出自动编码效果,例如将单号自动+1后,产生该笔单号 Table说明 SQL语法 SELECT 'A'+REPLICATE('0',7-len( ...

  4. ABAP SQL取最大值及聚合函数OUNT, AVG, MAX的简单例子 SAP

    在ABAP里取最大值,有好几种方法 第一种 SELECT posnr "项目号FROM resb AS aJOIN afko AS b ON a~aufnr = b~aufnrINTO TA ...

  5. sql两个数字之差取最接近的_从零学DAX/Sql/Python030203SQL数据分类汇总续篇

       点击"数字化审计",可以关注哦! 开篇啰嗦话 上篇文章,为你介绍了SQL语句中select 的group by参数进行分类统计,group by在审计数据分析过程中是必然绕不 ...

  6. python从数据库取数据 显示字段名_如何在python中将SQL数据库中的字段名放入列表中...

    以下是我目前掌握的代码:from ConfigParser import * import MySQLdb configuration = ConfigParser() configuration.r ...

  7. select函数fdwrite用法_通俗易懂的学会:SQL窗口函数

    ​一.窗口函数有什么用? 在日常工作中,经常会遇到需要在每组内排名,比如下面的业务需求: 排名问题:每个部门按业绩来排名 topN问题:找出每个部门排名前N的员工进行奖励 面对这类需求,就需要使用sq ...

  8. sql limit不接具体数字_这21个写SQL的好习惯,你要养成呀

    前言 每一个好习惯都是一笔财富,本文分SQL后悔药, SQL性能优化,SQL规范优雅三个方向,分享写SQL的21个好习惯,谢谢阅读,加油哈~ 公众号:「捡田螺的小男孩」 1. 写完SQL先explai ...

  9. java sql 查询中的转义序列不对_在 JDBC 中使用 SQL 转义序列 - SQL Server | Microsoft Docs...

    使用 SQL 转义序列Using SQL escape sequences 08/12/2019 本文内容 按照 JDBC API 的定义,Microsoft JDBC Driver for SQL ...

最新文章

  1. 2022-2028年中国热熔胶产业竞争现状及发展规模预测报告
  2. RDKit | 基于RDKit和scikit-learn的KNN模型预测Ames的致突变性
  3. linux 指令tftp传输文件_tftp命令_Linux tftp 命令用法详解:在本机和tftp服务器之间使用TFTP协议传输文件...
  4. corosync/openais+pacemaker+drbd+web实现高可用群集
  5. java类的结构:构造器 —(13)
  6. tornado 第一篇
  7. Android设计模式之——责任链模式
  8. linux连接mysql_主机Navicat连接linux(虚拟机)的mysql数据库
  9. 为什么复制粘贴格式总是出错_想把图片转换成pdf格式怎么做?你找对方法了吗...
  10. cmake mysql 参数_MySQL cmake编译时这些参数是什么意思?-问答-阿里云开发者社区-阿里云...
  11. 基于机器学习的恶意网站/仿冒网站检测实战
  12. 融合应急指挥调度系统
  13. Java调用第三方http接口的方式
  14. LVM逻辑管理器(Logical volume Manager)
  15. 《故障排除》——VMware Horizon agent:failed to install vmwusm driveer| winerror code 3758096967
  16. 机会总是留给有准备的人 —— 从裁缝到码农
  17. 算法入门到进阶(二)——STL和基本数据结构(vector和栈)
  18. datetime的时值
  19. 分享3款有消除笔的p图软件,简单易上手
  20. 金蝶系统服务器上怎样备份文件,金蝶服务器数据库备份

热门文章

  1. zabbix 监控 elasticsearch
  2. Linux执行命令时遇到的些问题
  3. 网络之XML解析-原生
  4. C/C++基础面试题集锦
  5. 创建文档库时指定文件夹(路径)
  6. Open XML 已成为ISO标准
  7. 面试必问:十大经典排序算法总结
  8. 基于SSM实现学籍管理系统
  9. Jsp实现停车场管理系统
  10. weblogic介绍