当前位置: 首页 > news >正文

SQL 常用 OVER() 窗口函数介绍

1. sum() + over()  做组内数据累加

       在 SQL 中想实现不同分组内数据累加,可以通过 sum() + over() PARTITION BY + ORDER BY  结合实现。这种方式能同时满足多维度分组且组内累加的需求,示例如下:

假设我们有一张 sales 表,表中存储着不同区域、不同产品的每日销售额,数据如下:

sale_idregionproductsale_dateamount
1华北手表2023-10-021000
2华北手表2023-10-031500
3华北平板2023-10-023000
4华东手表2023-10-033000
5华东手表2023-10-033500
6华东平板2023-10-034000

需求:按 region(区域)和 product(产品)分组,在每个分组内按时间顺序累加金额。

实现方法:SUM()+OVER()+PARTITION BY+ORDER BY

SELECT sale_id,region,product,sale_date,amount,-- 按区域和产品分组,组内按日期排序累加金额SUM(amount) OVER (PARTITION BY region, product  -- 多列分组:区域+产品ORDER BY sale_date            -- 组内按日期排序ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW  -- 累加范围:从组内第一条到当前行) AS cumulative_amount
FROM sales
ORDER BY region, product, sale_date;

结果:

sale_id | region  | product | sale_date  | amount | cumulative_amount
---------|---------|---------|------------|--------|------------------
1       | 华北    | 手表    | 2023-10-02 | 1000   | 1000     -- 华北手表:1000
2       | 华北    | 手表    | 2023-10-02 | 1500   | 2500     -- 华北手表:1000+1500
3       | 华北    | 手表    | 2023-10-03 | 3000   | 5500     -- 华北手表:1000+1500+3000
4       | 华东    | 手表    | 2023-10-03 | 3500   | 9000     -- 华东手表:1000+1500+3000+3500
5       | 华东    | 平板    | 2023-10-02 | 3000   | 3000     -- 华东平板:3000
6       | 华东    | 平板    | 2023-10-03 | 4000   | 7000     -- 华东平板:3000+4000

 关键语法: 

  1. PARTITION BY col1, col2:按多列组合进行分组,所有列相同的数据会被分到同一组。

  2. ORDER BY:指定组内的排序规则,决定累加的顺序。

      3.  窗口函数支持所有主流数据库(MySQL 8.0+、PostgreSQL、Kingbase、Orecle 等)

2. OVER() 窗口函数介绍

       SELECT  sale_id, region, product, sale_date,  amount, SUM(amount) OVER (
PARTITION BY region, product   ORDER BY sale_date  
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS cumulative_amount  FROM sales ORDER BY region, product, sale_date;

        在上面的 sql 中,OVER()窗口函数核心语法是定义一个数据窗口,可以理解为定义组内其它数据与当前行处理逻辑,例如上面 sql 的逻辑是,同一个分组内从第一行开始将数据累加到当前行。         注意:上面 sql 看似与 GROUP BY 处理相同,其实所有区别,窗口函数不会将多行数据合并为一行,而是在原有行的数据基础上为每行添加一个计算结果。

     2.1 基本使用语法
函数名(列名) OVER (窗口定义)

        1. 函数名:可以是聚合函数(SUMCOUNTAVG 等)或专用窗口函数(ROW_NUMBERRANKDENSE_RANK 等)。

        2. 窗口定义:通过 PARTITION BYORDER BY 等子句定义数据窗口对数据处理范围和规则。

    2.2  关键字说明

        1. PARTITION BY: 分组划分规则(可选),将数据按指定列分组,每个分组形成一个独立的空间,函数只在组内计算。

SELECT sale_date,region,amount,SUM(amount) OVER (PARTITION BY region ORDER BY sale_date) AS 区域累计销售额
FROM sales;

        2. ORDER BY:窗口内排序(可选),指定窗口内数据的排序规则

SELECT sale_date,amount,SUM(amount) OVER (ORDER BY sale_date) AS 全局累计销售额
FROM sales;

       3. 处理逻辑范围(可选),通过 ROWS 或 RANGE 精确指定窗口包含的行范围(默认是从组内第一行到当前行):

    3.1 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW :从组内第一行到当前行

    3.2 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING :从当前行到组内最后一行

    3.3 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ;当前行、前一行、后一行(共 3 行)

SELECT sale_date,amount,AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS 近3行平均值
FROM sales;

3. 常见使用场景

  3.1  累计求和 / 平均值(聚合函数 +OVER()
SELECT id,amount,-- 累计求和SUM(amount) OVER (ORDER BY id) AS 累计金额,-- 移动平均值(前1行+当前行+后1行)AVG(amount) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS 移动平均
FROM sales;
3.2 组内排名(ROW_NUMBER/RANK/DENSE_RANK
SELECT region,amount,-- 组内按金额排名(不重复)ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS 排名_不重复,-- 组内按金额排名(允许并列,跳过后续名次)RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS 排名_跳号,-- 组内按金额排名(允许并列,不跳过后续名次)DENSE_RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS 排名_连续
FROM sales;
3.3 组内首尾值 / 占比
SELECT region,amount,-- 组内最大金额MAX(amount) OVER (PARTITION BY region) AS 区域最高金额,-- 当前金额占组内总金额的比例amount / SUM(amount) OVER (PARTITION BY region) AS 区域占比
FROM sales;

与 GROUP BY 的区别

特性GROUP BYOVER() 窗口函数
结果行数每组返回一行保留原表所有行
计算范围整组数据可自定义窗口范围(如前 N 行)
适用场景统计各组汇总值需保留明细行的分析场景

总结

OVER() 函数的核心价值是:在不减少原表行数的前提下,实现对 "相关数据组" 的灵活计算,特别适合需要同时展示明细数据和聚合分析结果的场景(如报表中的累计占比、排名、移动平均等)。


文章转载自:

http://yL6f0l2y.wbgxz.cn
http://kBLSLdvW.wbgxz.cn
http://owHH38Bw.wbgxz.cn
http://c63QEL1V.wbgxz.cn
http://BFFpsOEl.wbgxz.cn
http://hxo8tqad.wbgxz.cn
http://s1vCaY0N.wbgxz.cn
http://VIraH4CU.wbgxz.cn
http://zL18NMfI.wbgxz.cn
http://QQ7wFHDy.wbgxz.cn
http://kE0oahNJ.wbgxz.cn
http://8HqPx4Gr.wbgxz.cn
http://u80V49Ms.wbgxz.cn
http://fcygOaUq.wbgxz.cn
http://Eb60vjB9.wbgxz.cn
http://C7RX37yT.wbgxz.cn
http://ePcMbKb6.wbgxz.cn
http://EwUaI6BH.wbgxz.cn
http://lidfH1T2.wbgxz.cn
http://OArqe5fi.wbgxz.cn
http://Rhpp2aQM.wbgxz.cn
http://h5XLh1kq.wbgxz.cn
http://luwx2ZYy.wbgxz.cn
http://jdRBcjoa.wbgxz.cn
http://gNLPK8NI.wbgxz.cn
http://XANyN3OB.wbgxz.cn
http://jOfygSGk.wbgxz.cn
http://UQkIRHun.wbgxz.cn
http://2MdZCzyE.wbgxz.cn
http://kcjg0h8c.wbgxz.cn
http://www.dtcms.com/a/369520.html

相关文章:

  • 【开题答辩全过程】以 在线教育系统为例,包含答辩的问题和答案
  • SQL基础与DDL
  • 嵌入式ARM64 基于RK3588原生SDK添加用户配置选项./build lunch debian
  • 基于w5500的stm32f103 实战项目
  • Python 算数运算练习题
  • FastDDS:第三节(3.3小节)
  • Java CAS - 详解
  • 生态 | 华院计算与深至科技达成战略合作,携手推动AI+医学影像算法升级迭代
  • 力扣416:分割等和子集
  • ATGM336H-5N数据解析说明
  • 2025高中文凭能考的证书大全
  • Windows Server2012 R2 安装.NET Framework 3.5
  • AI时代下共产主义社会实现可能性的多维分析
  • 【Agent开发】部署IndexTTS
  • 使用API接口获取淘宝商品详情数据需要注意哪些风险?
  • 消费品企业客户数据分散?CRM 系统来整合
  • STM32项目分享:面向复杂路段的可控智能交通信号灯设计
  • 【完整源码+数据集+部署教程】加工操作安全手套与手部检测系统源码和数据集:改进yolo11-cls
  • 当洗地机开始「懂你」:VTX316如何让科技更有温度
  • 深度学习模型在边缘计算设备上的部署
  • 【C++题解】贪心和模拟
  • 小学生学习机如何选?AI英语与护眼是关键
  • centos 系统如何安装open jdk 8
  • Git 工具的「安装」及「基础命令使用」
  • PCB 残胶怎么除?猎板分享高效且安全的去除工艺方案
  • 基于FPGA实现数字QAM调制系统
  • 【代码随想录算法训练营——Day2】链表——203.移除链表元素、707.设计链表、206.反转链表
  • GEO公司有哪些:AI时代品牌可见性策略全景分析
  • 迁移学习的案例
  • Linux 入门到精通,真的不用背命令!零基础小白靠「场景化学习法」,3 个月拿下运维 offer,第二十七天