(课堂笔记回顾)聚合函数、开窗函数

SQL核心函数


聚合函数:SUM/AVG/MAX/MIN/COUNT实现数据汇总,GROUP BY分组后HAVING过滤组级结果。注意COUNT(*)包含NULL,COUNT(列)忽略NULL。


窗口函数:通过OVER子句实现高级分析,包含五大类:

  1. 排名函数:ROW_NUMBER/RANK/DENSE_RANK
  2. 取值函数:LAG/LEAD获取相邻行,FIRST_VALUE取首项
  3. 分片函数:NTILE数据分桶
  4. 聚合窗口:SUM/AVG实现滚动累计
  5. 偏移分析:同比环比计算

关键区别:聚合函数压缩行数,窗口函数保留原数据行数。执行顺序上窗口函数在GROUP BY之后处理。


📊 昨日回顾 - 复习笔记

一、聚合函数

核心语法

sql

复制代码
SELECT 
    字段,
    聚合函数(列) AS 别名
FROM 表
WHERE 行级过滤条件
GROUP BY 分组字段
HAVING 组级过滤条件(可使用聚合函数)
ORDER BY 排序字段;

聚合函数一览

函数 作用 空值处理
SUM(列) 求和 忽略NULL
AVG(列) 平均值 忽略NULL
MAX(列) 最大值 忽略NULL
MIN(列) 最小值 忽略NULL
COUNT(列) 计数 忽略NULL
COUNT(*) 总行数 包含NULL
COUNT(1) 总行数 包含NULL

COUNT 的区别

sql

复制代码
COUNT(字段)  -- 排除NULL值,统计非空行数
COUNT(*)     -- 统计所有行,包含NULL
COUNT(1)     -- 统计所有行,性能略优于COUNT(*)

核心规则

规则 说明
SELECT约束 非分组字段、非聚合值不能出现在SELECT中
HAVING 只用于聚合值过滤(如总薪资>10000)
WHERE 用于行级过滤(如薪资>1000)
NULL处理 空值不参与聚合计算

二、窗口函数(开窗函数)

基础语法

sql

复制代码
函数() OVER (PARTITION BY 分组字段 ORDER BY 排序字段)

五种窗口函数类型

类型 函数 用途
排名类 ROW_NUMBER(), RANK(), DENSE_RANK() 取TOP N
取值类 LAG(), LEAD(), FIRST_VALUE() 同环比、上下行
分片类 NTILE() 数据切片/分桶
聚合类 SUM(), AVG(), COUNT() 累计、占比
偏移类 LAG(), LEAD() 偏移取值

三、排名函数详解

三种排名对比

函数 效果 示例
ROW_NUMBER() 连续不重复 1,2,3,4
RANK() 有间隔 1,1,3,4
DENSE_RANK() 无间隔 1,1,2,3

示例数据(张三、李四的成绩)

sql

复制代码
姓名    科目    成绩    ROW_NUMBER    RANK    DENSE_RANK
---------------------------------------------------------
张三    英语    105       1           1          1
张三    语文    98        2           2          2
张三    数学    76        3           3          3
李四    语文    99        1           1          1
李四    数学    78        2           2          2
李四    英语    66        3           3          3

四、LAG / LEAD(同环比计算)

语法

sql

复制代码
LAG(目标字段, 偏移量, 缺省值) OVER (PARTITION BY 分组 ORDER BY 排序)
LEAD(目标字段, 偏移量, 缺省值) OVER (PARTITION BY 分组 ORDER BY 排序)

示例数据

sql

复制代码
-- 按姓名分组,按成绩排序,取上一行科目
姓名    科目    成绩    LAG(科目)   说明
---------------------------------------------
张三    数学    76      NULL        -- 成绩最低,无上一行
张三    英语    105     数学         -- 上一行是数学
张三    语文    98      英语         -- 上一行是英语
李四    英语    66      NULL        -- 成绩最低,无上一行
李四    数学    78      英语         -- 上一行是英语
李四    语文    99      数学         -- 上一行是数学

五、FIRST_VALUE(取首个值)

语法

sql

复制代码
FIRST_VALUE(目标字段) OVER (PARTITION BY 分组 ORDER BY 排序)

示例数据

sql

复制代码
-- 按姓名分组,按成绩降序,取最高分科目
姓名    科目    成绩    FIRST_VALUE(科目)   说明
---------------------------------------------
张三    英语    105     英语                -- 最高分科目
张三    语文    98      英语                -- 全部显示英语
张三    数学    76      英语                -- 全部显示英语
李四    语文    99      语文                -- 最高分科目
李四    数学    78      语文                -- 全部显示语文
李四    英语    66      语文                -- 全部显示语文

六、NTILE(数据切片)

语法

sql

复制代码
NTILE(桶数) OVER (PARTITION BY 分组 ORDER BY 排序)

示例数据(2个桶,按成绩从高到低)

sql

复制代码
姓名    科目    成绩    NTILE(2)   说明
----------------------------------------
张三    英语    105       1        -- 前50%
张三    语文    98        1        -- 前50%
张三    数学    76        2        -- 后50%
李四    语文    99        1        -- 前50%
李四    数学    78        1        -- 前50%
李四    英语    66        2        -- 后50%

七、聚合型开窗

三种模式对比

1. 全局窗口(无PARTITION,无ORDER BY)

sql

复制代码
SUM(成绩) OVER ()
姓名 科目 成绩 全局总和
张三 语文 98 522
张三 数学 76 522
张三 英语 105 522
李四 语文 99 522
李四 数学 78 522
李四 英语 66 522
2. 分组窗口(有PARTITION,无ORDER BY)

sql

复制代码
SUM(成绩) OVER (PARTITION BY 姓名)
姓名 科目 成绩 个人总和
张三 语文 98 279
张三 数学 76 279
张三 英语 105 279
李四 语文 99 243
李四 数学 78 243
李四 英语 66 243
3. 累计窗口(有PARTITION + ORDER BY)

sql

复制代码
SUM(成绩) OVER (ORDER BY 成绩)  -- 全局累计
SUM(成绩) OVER (PARTITION BY 姓名 ORDER BY 成绩)  -- 组内累计

全局累计(按成绩升序):

姓名 科目 成绩 全局累计 计算过程
李四 英语 66 66 66
张三 数学 76 142 66+76
李四 数学 78 220 66+76+78
张三 语文 98 318 +98
李四 语文 99 417 +99
张三 英语 105 522 +105

组内累计(按姓名分组,按成绩升序):

姓名 科目 成绩 组内累计 计算过程
张三 数学 76 76 76
张三 语文 98 174 76+98
张三 英语 105 279 76+98+105
李四 英语 66 66 66
李四 数学 78 144 66+78
李四 语文 99 243 66+78+99

八、执行顺序对比

聚合函数执行顺序

text

复制代码
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

窗口函数执行顺序

text

复制代码
FROM → WHERE → GROUP BY → HAVING → 窗口函数 → SELECT → ORDER BY

⚠️ 重点 :窗口函数在 GROUP BY 和 HAVING 之后执行


九、快速记忆卡

text

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    聚合函数 vs 窗口函数                        │
├─────────────────────────────────────────────────────────────┤
│  聚合函数:GROUP BY 压缩行数,HAVING 过滤组                    │
│  窗口函数:PARTITION BY 保留行数,OVER 开窗计算                │
├─────────────────────────────────────────────────────────────┤
│  排名:ROW_NUMBER (连续) / RANK (跳号) / DENSE_RANK (不跳)    │
│  取值:LAG (上一行) / LEAD (下一行) / FIRST_VALUE (首行)      │
│  分片:NTILE(N) 分成 N 份                                     │
│  累计:SUM/AVG OVER (ORDER BY) 实现滚动计算                   │
├─────────────────────────────────────────────────────────────┤
│  口诀:                                                      │
│  "分组聚合用GROUP,开窗计算用PARTITION"                       │
│  "WHERE行过滤,HAVING组过滤"                                  │
│  "排名就在OVER里,TOP N轻松取"                                │
└─────────────────────────────────────────────────────────────┘
相关推荐
Irene19917 天前
(课堂笔记)Oracle 窗口函数/开窗函数/分析函数
oracle·开窗函数
Irene19917 天前
(课堂笔记)Oracle 聚合函数与 GROUP BY 分组查询
oracle·聚合函数
Captain_Data19 天前
SQL聚合函数与分组统计:数据分析核心技能
数据库·sql·mysql·数据分析·group by·聚合函数
7澄15 个月前
MySQL 数据库进阶:SQL 查询语句全解析
数据库·mysql·查询·模糊查询·条件查询·聚合函数·基础查询
IT成长日记1 年前
【MySQL基础】聚合函数从基础使用到高级分组过滤
数据库·mysql·聚合函数
加勒比之杰克1 年前
【数据库初阶】表的查询语句和聚合函数
数据库·增删改查·聚合函数
Amd7941 年前
深度剖析 GROUP BY 和 HAVING 子句:优化 SQL 查询的利器
sql·性能优化·数据分析·group by·聚合函数·数据分组·having
F_D_Z2 年前
【SQL】有趣的电影
数据库·sql·mysql·聚合函数
苏生Susheng2 年前
【Oracle】Oracle中的LISTAGG函数
java·数据库·sql·mysql·oracle·聚合函数·listagg函数