SQL - 开窗(窗口)函数

这篇具有很好参考价值的文章主要介绍了SQL - 开窗(窗口)函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是开窗函数?

开窗函数对一组值进行操作,它不像普通聚合函数那样需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列

开窗函数的语法形式为:函数 + over(partition by <分组用列> order by <排序用列>),表示对数据集按照分组用列进行分区,并且并且对每个分区按照函数聚合计算,最终将计算结果按照排序用列排序后返回到该行。括号中的两个关键词partition by 和order by 可以只出现一个。

注意:开窗函数不会互相干扰,因此在同一个查询语句中可以同时使用多个开窗函数

开窗函数适用于 mysql 8.0以上版本, sql sever 、hive、oracle 等

测试数据

create table score (
    grade VARCHAR(10) not null,
    subject VARCHAR(10) not null,
    name VARCHAR(50) not null,
    score int not null
);

INSERT INTO score (grade, subject, name, score) VALUES ('Grade1', '语文', 'John', 90), 
('Grade2', '语文', 'Amy', 70), 
('Grade1', '语文', 'Mike', 80), 
('Grade2', '语文', 'Lisa', 80), 
('Grade2', '语文', 'Tom', 90),
('Grade1', '英语', 'John', 80), 
('Grade2', '英语', 'Amy', 90), 
('Grade1', '英语', 'Mike', 80), 
('Grade2', '英语', 'Lisa', 90), 
('Grade2', '英语', 'Tom', 100);

一、排序开窗函数

-- 一、排序开窗函数
-- ① row_number() -- 相同值排名连续,返回结果1、2、3、4
-- ② rank() -- 相同值排名相同,后续排名不连续,返回结果为 1、2、2、4
-- ③ dense_rank() -- 相同值排名相同,后续排名连续,返回结果为 1、2、2、3
-- ④ ntile(n) -- 分组排名,将数据分为n组并返回对应组号1、2......n
select grade
,subject
,score
-- ,row_number() over(partition by subject order by score desc) as row_numbers
-- ,rank() over(partition by subject order by score desc) as ranks
-- ,dense_rank() over(partition by subject order by score desc) as dense_ranks
,ntile(2) over(partition by subject order by score desc) as ntiles
from score;

1.1、row_number

,row_number() over(partition by subject order by score desc) as row_numbers

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

 1.2、rank

,rank() over(partition by subject order by score desc) as ranks

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

 1.3、dense_rank

,dense_rank() over(partition by subject order by score desc) as dense_ranks

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

 1.4、ntile

,ntile(2) over(partition by subject order by score desc) as ntiles

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

二、聚合开窗函数

-- 二、聚合开窗函数, 【有order by ,组内依不连续次序聚合;无order by 组内聚合】
-- ① sum() -- 分组求和
-- ② count() -- 分组求总数
-- ③ min() -- 分组求最小值
-- ④ max() -- 分组求最大值
-- ⑤ avg() --分组求均值
select grade
,subject
,score
-- ,sum(score) over(partition by subject) as sum聚合no_order_by
-- ,sum(score) over(partition by subject order by score desc) as sum聚合order_by
-- ,count(score) over(partition by subject) as count聚合no_order_by
-- ,count(score) over(partition by subject order by score desc) as count聚合order_by
-- ,min(score) over(partition by subject) as min聚合no_order_by
-- ,min(score) over(partition by subject order by score desc) as min聚合order_by
-- ,max(score) over(partition by subject) as max聚合no_order_by
-- ,max(score) over(partition by subject order by score desc) as max聚合order_by
-- ,avg(score) over(partition by subject) as avg聚合no_order_by
-- ,avg(score) over(partition by subject order by score desc) as avg聚合order_by
from score;

2.1、sum

2.1.1 不带order by
,sum(score) over(partition by subject) as sum聚合no_order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.1.2 带有order by
,sum(score) over(partition by subject order by score desc) as sum聚合order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.2、count

2.2.1 不带order by
,count(score) over(partition by subject) as count聚合no_order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

 2.2.2 带有 order by
,count(score) over(partition by subject order by score desc) as count聚合order_by
SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.3 min

2.3.1 不带order by
,min(score) over(partition by subject) as min聚合no_order_by
SQL - 开窗(窗口)函数,sql,数据库,开窗函数
2.3.2 带有order by
,min(score) over(partition by subject order by score desc) as min聚合order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.4 max

2.4.1 不带order by
,max(score) over(partition by subject) as max聚合no_order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.4.2 带有order by
,max(score) over(partition by subject order by score desc) as max聚合order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.5 avg

2.5.1 不带order by
,avg(score) over(partition by subject) as avg聚合no_order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

2.5.2 带有order by
,avg(score) over(partition by subject order by score desc) as avg聚合order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

三、其他开窗函数

-- 三、其他开窗函数
-- ① lag(字段名,n,0) -- 落后移位开窗函数,表示返回向后第n行指定字段对应数据。其中n代表向后偏移n行,0代表若偏移行数超出表范围则返回0也可以改成其他值,若不写则默认null
-- ② lead(字段名,n,0) -- 超前移位开窗函数,与lag()相反,表示返回向前第n行指定字段对应数据
-- ③ first_value() -- 取分组后截止到当前行,排序后第一个值
-- ④ last_value() -- 取分组后截止到当前行,排序后最后一个值
-- 【oracle独有函数】⑤ ratio_to_report(字段名) over(partition by 字段名) -- 百分比分析函数,ratio_to_report(字段名) 为分子,over(partition by 字段名) 为分母,若分母中partition by 字段名 省略则表示占数据集整体百分比。为Oracle数据库函数,mysql不能使用
select grade
,subject
,score
,lag(score,1,0) over(partition by subject) as lag移位no_order_by
-- ,lag(score,2,-1) over(partition by subject) as lag移位no_order_by
-- ,lag(score,3,null) over(partition by subject) as lag移位no_order_by
-- ,lag(score,1,0) over(partition by subject order by score desc) as lag移位order_by
-- ,lead(score,1,0) over(partition by subject order by score desc) as lead移位order_by
-- ,lead(score,2,null) over(partition by subject order by score desc) as lead移位order_by
-- ,lead(score,3,1000) over(partition by subject order by score desc) as lead移位order_by
-- ,first_value(score) over(partition by subject) as first_value排序1
-- ,last_value(score) over(partition by subject) as last_value排序1
-- ,first_value(score) over(partition by subject order by score desc) as first_value排序1
-- ,last_value(score) over(partition by subject order by score desc) as last_value排序1
from score;

3.1 lag

3.1.1 不带order by
,lag(score,1,0) over(partition by subject) as lag移位no_order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

,lag(score,1,0) over(partition by subject) as lag移位no_order_by
,lag(score,2,-1) over(partition by subject) as lag移位no_order_by
,lag(score,3,null) over(partition by subject) as lag移位no_order_by
SQL - 开窗(窗口)函数,sql,数据库,开窗函数
3.1.2 带有 order by
,lag(score,1,0) over(partition by subject order by score desc) as lag移位order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

3.2 lead

,lead(score,1,0) over(partition by subject order by score desc) as lead移位order_by
,lead(score,2,null) over(partition by subject order by score desc) as lead移位order_by
,lead(score,3,1000) over(partition by subject order by score desc) as lead移位order_by

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

3.3  first_value 和 last_value

3.3.1 不带order by
,first_value(score) over(partition by subject) as first_value排序1
,last_value(score) over(partition by subject) as last_value排序1

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

3.3.1 带有 order by
,first_value(score) over(partition by subject order by score desc) as first_value排序1
,last_value(score) over(partition by subject order by score desc) as last_value排序1

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

四、开窗函数的定位框架

-- 四、开窗函数的定位框架
-- 在order by 后存在可省略的窗口框架 range/rows between x and y ,主要用于对partition by的分组排序后结果做进一步限制,并定位出限制后的运算范围。
-- range表示按照值的范围进行定义,而rows表示按照行的范围进行定义。
-- 若order by 后未指定框架,那么默认框架将采用 range unbounded preceding and current row,表示按照值的排序范围进行范围的定义,从开窗后的第一行到当前行。
-- 若窗口函数没有order by,也就不存在框架range/rows between x and y。
-- 框架range/rows between x and y 具体x、y可取值见下表:
-- 		可取值								含义
-- unbounded preceding			partition by 分组order by后 第一行
-- unbounded following			partition by 分组order by后 最后一行
-- current row					partition by 分组order by后 当前行
-- n preceding					partition by 分组order by后 前n行
-- n following					partition by 分组order by后 后n行
-- 一般来讲,range 只支持使用 unbounded preceding、 unbounded following、current row,若是要使用n preceding 和n following	则前提是这个字段支持加减n(int、long、日期类型),然后n preceding 则相当于在此行值的基础上减去n后的值作为上界
select grade
,subject
,score
-- ,sum(score) over(partition by subject order by score desc) as sum聚合默认
-- ,sum(score) over(partition by subject order by score desc rows between unbounded preceding and current row) as sum聚合rows_preceding
-- ,sum(score) over(partition by subject order by score desc rows between current row and unbounded following) as sum聚合rows_preceding
-- ,sum(score) over(partition by subject order by score desc range between unbounded preceding and current row) as sum聚合range
-- ,sum(score) over(partition by subject order by score desc range between current row and unbounded following) as sum聚合range_following
-- ,sum(score) over(partition by subject order by score desc rows between 2 preceding and 1 following) as sum聚合2_1
,sum(score) over(partition by subject order by score desc range between 1 preceding and 1 following) as sum聚合range
from score;

4.1 range

,sum(score) over(partition by subject order by score desc) as sum聚合默认
,sum(score) over(partition by subject order by score desc range between unbounded preceding and current row) as sum聚合range
,sum(score) over(partition by subject order by score desc range between current row and unbounded following) as sum聚合range_following

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

4.2 rows

,sum(score) over(partition by subject order by score desc rows between unbounded preceding and current row) as sum聚合rows_preceding
,sum(score) over(partition by subject order by score desc rows between current row and unbounded following) as sum聚合rows_following

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

 
 

,sum(score) over(partition by subject order by score desc rows between 2 preceding and 1 following) as sum聚合2_1
,sum(score) over(partition by subject order by score desc rows between current row and 1 following) as sum聚合current_1

SQL - 开窗(窗口)函数,sql,数据库,开窗函数

参考:SQL函数 - 开窗(窗口)函数 - 知乎文章来源地址https://www.toymoban.com/news/detail-664185.html

到了这里,关于SQL - 开窗(窗口)函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SQL_求店铺的topN && 开窗函数数据倾斜

    某互联网大厂的一道比较有深度的面试题, 参考文章 : hive|性能优化|_Hive ROW_NUMBER TopN 性能优化 有50W个 店铺,每个顾客访客访问任何一个店铺的任何一个商品时都会产生一条访问日志, 访问日志存储的表名为Visit,访客的用户id为user_id,被访问的店铺名称为shop,数据如下:

    2024年02月15日
    浏览(49)
  • MySQL数据库基础(三):多表查询,子查询,开窗函数

    表与表之间的关系 在SQL语句中,数据表与数据表之间,如果存在关系,一般一共有3种情况: ① 一对一关系(高级) 比如有A、B两张表,A表中的每一条数据,在B表中有一条唯一的数据与之对应。 用户表user user_id(用户编号) 账号username 密码password 001 admin admin888 002 itheima

    2024年02月12日
    浏览(45)
  • SQL Server判断数据库、表、列、视图、存储过程、函数是否存在

    在写一些业务逻辑相对复杂点的存储过程的时候,经常会用到临时表或者数据表作为临时结果的保存。但每次在作表是否存在的判断时,往往想不起完整的SQL写法。因此,记录一些常用的数据库对象是否存在的判断方法,可以达到快速查找的目的。正是:好记性不如烂笔头。

    2024年02月02日
    浏览(128)
  • 数据库SQL函数 根据身份证号/出生年月 精确计算年龄(Oracle/MySQL)

    问题 根据身份证号统计年龄(18位) Oracle 思路 (1)Substr()函数在Oracle使用中表示被劫取的字符串表达式,截取字符串的内容。 (2)To_date()函数可以转换不同格式的日期,通过使用to_date函数可以将字符串类型的日期转换成date格式。 (3)Months_between()函数反悔两个日期之间的

    2024年02月11日
    浏览(50)
  • SQL 的window开窗函数简单使用

    开窗函数不论是spark的还是clickhouse的在日常的查询中是一个很常用的功能,特别是他想要解决的问题和group by的很类似,这两种容易引起混淆,本文就简单的描述下开窗函数的简单用法 首先窗口函数和group by是完全没有交集的,他们完全没有任何关系,group by聚合数据后会导致

    2024年02月09日
    浏览(43)
  • SQL使用技巧(6)HIVE开窗函数

    开窗函数的使用铁律:不要滥用 先想明白自己要实现什么样的功能,然后再去实践。没有目的的尝试段不可取,会难以理解各开窗函数的真正用法。 如果没有现成可用HIVE库,可以参见本人 大数据单机学习环境搭建 系列文章。 1.1Hive建表 1.2数据准备 1.3保存为HDFS文件 1.4验证

    2024年02月08日
    浏览(59)
  • hive sql—开窗函数—累积求和和滑动求和

    数据集有三列数据,姓名、月份和数量: 图1 使用 sum() 函数和 over() 来实现,如下: 结果如下: 同一个name,后一个月份都是前几个月份的累加和 图2 需要稍微骚一点的操作,加上一个限制条件: 数字:可正可零可负,正往前,负向后;preceding:向前几行;following:向后几行

    2024年02月11日
    浏览(45)
  • 时序数据库TDengine窗口函数

    select ts, lp_index, max(lp_value),  lp_project_id, lp_variable_uri,  lp_time_ticks, lp_value_type_value, lp_value, lp_unit from weixingdata.tdm_lp_original_data where  lp_time_ticks = \\\'2023-11-27 12:38:41\\\'                 and lp_time_ticks =  \\\'2023-11-27 14:38:41\\\'       and  lp_project_id = \\\'0A66F139-F8BF-485A-9F3B-DECD40C3E6D9\\\'      and

    2024年02月20日
    浏览(49)
  • 【大数据之Hive】十六、Hive-HQL函数之窗口函数(开窗函数)

      先定义了窗口的大小(按行来算),然后对窗口内的行的数据进行计算,再将计算结果返回给改行。   窗口函数包括窗口和函数两部分,窗口用于定义计算范围,函数用于定义计算逻辑,窗口函数只会在原来的表上增加一列结果列,不改变原来的数据。 函数:   绝

    2024年02月11日
    浏览(40)
  • SQL Server 数据库之SQL Server 数据库的安全设置

    数据库服务器是所有应用的数据中转站,若数据库服务被恶意攻击,可能会造成数据泄露、数据丢失、数据被恶意篡改等诸多无法挽回的损失; 所以,对数据库进行安全设置是每一个数据库管理人员都应掌握的知识; SQL Server 登录模式分为 “Windows 身份验证模式” 和 “SQL

    2024年02月06日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包