利用row_number函数处理重复数据

本文介绍了一种使用SQL的row_number()函数去除重复记录的方法。通过创建含有重复数据的测试表person,演示了如何利用row_number()函数配合partition by子句来筛选并保留每组中的第一条记录,最终将去重后的数据保存到新表tmp中。
 
利用row_number函数处理重复数据
 
--创建测试表person
CREATE TABLE person(
    sn varchar(10),
    name varchar(50)
);
go
 
--插入测试重复数据
insert into person values('1','guoqiang1');
insert into person values('1','guoqiang1');
insert into person values('1','guoqiang1');
insert into person values('2','guoqiang2');
insert into person values('2','guoqiang2');
insert into person values('3','guoqiang3');
go
 
--查看person
select * from dbo.person;
go
 
--去除重复数据,并放到tmp表中
select sn,name into tmp from
(select *, row_number() over(partition by sn order by sn) as rank from person) as t
where t.rank = 1
go
 
--查看tmp
select * from dbo.tmp
go
 
 
### 什么是 ROW_NUMBER() 函数ROW_NUMBER() 是 SQL 中一个重要的窗口函数,主要用于为查询结果集中的每一行分配一个唯一的连续整数编号。这个编号的生成基于指定的排序顺序,并且可以在每个分区(如果使用了 `PARTITION BY` 子句)内独立计算[^3]。 与传统的行号功能不同,ROW_NUMBER() 提供了更强大的灵活性和控制能力,允许用户根据特定需求对数据进行编号。它广泛应用于数据分页、排名分析以及复杂的数据处理任务中。 ### ROW_NUMBER() 的基本语法 ```sql ROW_NUMBER() OVER ( [PARTITION BY partition_expression, ... ] ORDER BY sort_expression [ASC | DESC], ... ) ``` - `PARTITION BY`:将数据划分为多个逻辑分区,ROW_NUMBER() 在每个分区内单独计数。 - `ORDER BY`:定义每一行在分区内的排序规则,从而决定编号的顺序。 ### 常见用途和使用示例 #### 示例1: 对查询结果添加行号 当需要为查询结果的每一行分配唯一编号时,可以使用 ROW_NUMBER() 来实现。例如,从 `test_user` 表中查询所有记录并按 `id` 排序后添加编号列: ```sql SELECT ROW_NUMBER() OVER (ORDER BY id) AS 编号, * FROM test_user; ``` 该语句会在结果集中新增一列“编号”,并按照 `id` 升序排列为每条记录分配递增的整数[^2]。 #### 示例2: 按分组生成行号 在某些场景下,可能希望在不同的数据分组内部重新开始编号。此时可以结合 `PARTITION BY` 使用。例如,在 `orders` 表中按客户分组,并为每个客户的订单编号: ```sql SELECT customer_id, order_date, amount, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS order_seq FROM orders; ``` 此查询会为每个 `customer_id` 分区内的订单按日期排序并分配序列号,适用于跟踪客户订单的先后顺序。 #### 示例3: 数据去重与筛选 ROW_NUMBER() 可用于识别和删除重复数据。例如,查找 `employees` 表中每个部门工资最高的员工: ```sql WITH RankedEmployees AS ( SELECT department_id, employee_id, salary, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank FROM employees ) SELECT * FROM RankedEmployees WHERE rank = 1; ``` 通过在每个部门内按工资降序排列并选择排名为1的记录,可以快速获取每个部门薪资最高的员工信息。 #### 示例4: 实现分页查询 在 Web 应用中,数据分页是常见的需求。ROW_NUMBER() 可以帮助构建高效的分页机制。例如,获取第 2 页的数据,每页显示 10 条记录: ```sql WITH PagedData AS ( SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_num, * FROM products ) SELECT * FROM PagedData WHERE row_num BETWEEN 11 AND 20; ``` 通过限制 `row_num` 的范围,可以轻松地提取特定页面的数据内容。 ### 注意事项 尽管 ROW_NUMBER() 非常强大,但在使用时也需要注意以下几点: - **唯一性问题**:当 `ORDER BY` 列存在重复值时,ROW_NUMBER() 仍然会为每行分配唯一的编号,但其顺序可能不可预测。 - **性能影响**:对于大数据量表,使用复杂的 `PARTITION BY` 和 `ORDER BY` 可能会影响查询性能,建议合理使用索引优化。 - **替代函数**:在某些情况下,如需允许重复编号,可以考虑使用 RANK() 或 DENSE_RANK() 等其他窗口函数。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值