ROW_NUMBER() OVER 用处

本文介绍如何使用SQL的ROW_NUMBER() OVER函数对表中的数据进行分组排序,并通过创建临时表和删除多余行的方式去除重复记录。以专辑数据为例,展示如何按歌曲名称和歌手进行分组,按插入日期排序,并最终删除重复行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ROW_NUMBER() OVER 

1,分组排序

2,删除重复行

CREATE TABLE album
(
  Id int identity (1,1),
  song_name varchar(1000),
  singer varchar(100),
  Insert_DT datetime
)
INSERT album VALUES ('song1','singer1', GETDATE()-1)
INSERT album VALUES ('song2','singer2', GETDATE()-2)
INSERT album VALUES ('song2','singer2', GETDATE()-3)
INSERT album VALUES ('song4','singer4', GETDATE()-4)
INSERT album VALUES ('song4','singer4', GETDATE()-5)
INSERT album VALUES ('song4','singer4', GETDATE()-6)
INSERT album VALUES ('song3','singer3', GETDATE()-7)

select * from album


select Rnum=row_number() over (partition by song_name, singer order by Insert_dt),*
from album

 

with [cte duplicate] as
(
select Rnum=row_number() over (partition by song_name, singer order by Insert_dt),*
from album
)
delete from [cte duplicate] where Rnum > 1

select * from album
--drop table album

 

<think>我们在处理关于MySQL中ROW_NUMBER()OVER函数的问题根据引用[2][3][4],我们知道ROW_NUMBER()是窗口函数,用于为每行分配唯一序号注意:MySQL在8.0版本才支持窗口函数基本语法:ROW_NUMBER()OVER([PARTITIONBYpartition_expression]ORDERBYorder_expression[ASC|DESC])我们需要提供使用示例,并解释其含义步骤:1.解释函数含义:ROW_NUMBER()分配唯一序号,即使排序值相同,序号也不同(区别于RANK和DENSE_RANK)2.说明PARTITIONBY子句:按某列分组,然后分别在各组内编号3.说明ORDERBY子句:按某列排序,序号根据排序结果递增4.给出示例:如不分组、分组、分页等常见场景注意:引用中提及分页、去重等用途,但用户直接问语法和示例,先聚焦基本用法准备两个示例:示例1:基本使用(无分组)示例2:分组使用(有PARTITIONBY)同时,因为引用[1]提到了分页,用户可能对分页应用感兴趣,所以也准备一个分页示例(利用ROW_NUMBER实现分页)但注意:ROW_NUMBER()不能直接用于LIMIT那样的分页,而是通过子查询实现“分页查询”,引用[3]提到了分页查询用途因此,示例3:用ROW_NUMBER实现分页另外,引用[4]提到ROW_NUMBER与RANK、DENSE_RANK的区别,可以简要说明由于用户没有要求对比,所以先给出核心内容,最后可附简要对比。回答结构:1.函数含义2.语法3.示例(基础、分组、分页)4.与RANK等对比(简短)5.注意事项(如MySQL版本要求)</think> ### MySQL中ROW_NUMBER() OVER函数的详解 #### 1. **函数含义** `ROW_NUMBER() OVER()`是MySQL 8.0+引入的**窗口函数**,用于为查询结果的每一行分配一个唯一的连续序号(即使排序字段相同也会严格递增)[^4]。 与其他排名函数(如`RANK()`)不同,它**不处理重复值**,序号始终唯一且连续[^3]。 #### 2. **核心语法** ```sql ROW_NUMBER() OVER ( [PARTITION BY 分组字段] -- 可选:按字段分组后独立编号 ORDER BY 排序字段 [ASC|DESC] -- 必选:按字段排序后生成序号 ) AS 别名 ``` - `PARTITION BY`:将数据分组,每组独立编号(如按部门分组)。 - `ORDER BY`:确定组内排序规则,序号按此顺序递增。 --- ### **使用示例** #### 示例1:基础排序(全局编号) ```sql SELECT id, name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num FROM employees; ``` **结果**: | id | name | salary | row_num | |----|-------|--------|---------| | 3 | 王五 | 9000 | 1 | | 1 | 张三 | 8000 | 2 | | 2 | 李四 | 7000 | 3 | > 按工资降序为所有员工生成唯一序号(工资相同则按默认顺序编号)[^2]。 --- #### 示例2:分组排序(组内编号) ```sql SELECT department, name, salary, ROW_NUMBER() OVER ( PARTITION BY department -- 按部门分组 ORDER BY salary DESC ) AS dept_rank FROM employees; ``` **结果**: | department | name | salary | dept_rank | |------------|-------|--------|-----------| | 技术部 | 王五 | 9000 | 1 | | 技术部 | 张三 | 8000 | 2 | | 销售部 | 李四 | 8500 | 1 | > 每个部门独立排序,组内最高工资者编号为1[^4]。 --- #### 示例3:高效分页查询 ```sql SELECT * FROM ( SELECT id, name, ROW_NUMBER() OVER (ORDER BY id) AS row_num FROM products ) AS temp WHERE row_num BETWEEN 6 AND 10; -- 获取第6~10行 ``` > 替代`LIMIT 5,5`,避免全表扫描,大幅提升大表分页性能[^3][^1]。 --- ### **与其他排序函数对比** | 函数 | 重复值处理 | 序号示例(值相同) | |----------------|----------------------|----------------------| | `ROW_NUMBER()` | 严格唯一 | 1,2,3(即使值相同) | | `RANK()` | 并列时跳过后续序号 | 1,1,3 | | `DENSE_RANK()` | 并列时不跳序号 | 1,1,2 | --- ### **注意事项** 1. **MySQL版本**:仅支持8.0及以上版本[^3]。 2. **性能优化**:结合`PARTITION BY`和索引可加速分组排序[^4]。 3. **去重应用**: ```sql DELETE FROM table WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY dup_column) AS rn FROM table ) t WHERE rn > 1 ); -- 删除重复数据 ``` [^1]: MySQL兼容PostgreSQL的分页语法`LIMIT row_count OFFSET offset`。 [^2]: `ROW_NUMBER() OVER`需指定`ORDER BY`排序规则。 [^3]: 适用于分页、去重、分组排序等场景。 [^4]: 即使排序字段相同,也会生成唯一序号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值