【MySQL基础】SQL窗口函数入门

1 窗口函数与聚合函数的本质区别

1.1 核心差异对比

特性

聚合函数

窗口函数

输出行数

合并为单行

保持原表行数

计算范围

全局或分组

自定义数据窗口

典型应用场景

统计汇总

复杂分析计算

1.2 直观示例对比

1.2.1 数据准备:

create table student (
    student_id int primary key,
    student_name char(50),
    class_id int,
    score int
);
commit;

insert into student values
(1, '张三', 1, 85),
(2, '李四', 1, 92),
(3, '王五', 2, 78),
(4, '赵六', 2, 95);
commit;

1.2.2 聚合函数示例

-- 统计各班平均分(结果合并)
select class_id, avg(score) 
from student 
group by class_id;

-- 结果
| class_id | avg(score) |
+----------+------------+
|        1 |    88.5 |
|        2 |    86.5 |

1.2.3 窗口函数示例

-- 显示每个学生的平均分
select student_name, score,
       avg(score) over (partition by class_id) as class_avg
from student;

-- 结果:
| student_name | score | class_avg |
|--------------|-------|-----------|
| 张三         | 85    | 88.5      |
| 李四         | 92    | 88.5      |
| 王五         | 78    | 86.5      |
| 赵六         | 95    | 86.5      |

2 三大核心窗口函数详解

2.1 ROW_NUMBER() 顺序编号

-- 应用场景:精确排名(无并列)
select student_name, score,
       row_number() over (order by score desc) as rank
from student;

-- 结果
| student_name | score | rank |
|--------------|-------|------|
| 赵六         | 95    | 1    |
| 李四         | 92    | 2    |
| 张三         | 85    | 3    |
| 王五         | 78    | 4    |

2.2 RANK() 跳跃排名

-- 应用场景:处理并列情况
-- 插入重复分数
insert into student values (5, '陈七', 1, 92);

select student_name, score,
       rank() over (order by score desc) as rank
from student;

-- 结果:
| student_name | score | rank |
|--------------|-------|------|
| 赵六         | 95    | 1    |
| 李四         | 92    | 2    |
| 陈七         | 92    | 2    |
| 张三         | 85    | 4    |
| 王五         | 78    | 5    |

2.3 NTILE() 数据分桶

-- 应用场景:将学生按成绩分为3个等级
select student_name, score,
       ntile(3) over (order by score desc) as grade_level
from student;

-- 结果:
| student_name | score | grade_level |
|--------------|-------|-------------|
| 赵六         | 95    | 1           |
| 李四         | 92    | 1           |
| 陈七         | 92    | 2           |
| 张三         | 85    | 2           |
| 王五         | 78    | 3           |

3 窗口函数高级技巧

3.1 多维度分析

-- 按班级分区后再按成绩排序
select student_name, class_id, score,
       rank() over (partition by class_id order by score desc) as class_rank
from student;

-- 结果:
| student_name | class_id | score | class_rank |
|--------------|----------|-------|------------|
| 李四         | 1        | 92    | 1          |
| 陈七         | 1        | 92    | 1          |
| 张三         | 1        | 85    | 3          |
| 赵六         | 2        | 95    | 1          |
| 王五         | 2        | 78    | 2          |

3.2 性能优化建议

-- 索引优化 
create index idx_score on student(score desc);
-- 避免全表窗口
-- 添加过滤条件
select * from (
  select student_name, score,
         row_number() over (order by score desc) as rn
  from student
) t where rn <= 3;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT成长日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值