SQL Server中如何筛选重复ServiceId对应的最大数值数据?
我懂你的需求啦——你想从TestDeleteTable表里,针对每个重复的ServiceId,只保留该ServiceId下第一列(我先假设这列叫ValueColumn,要是你实际列名不一样记得替换哦)数值最大的两行数据,对吧?你现在的查询只能统计每个ServiceId的重复次数,没法直接筛选出要保留的目标行,我给你几个实用的解决方案:
方案一:使用窗口函数(推荐,适配多数现代数据库)
如果你的数据库支持窗口函数(比如MySQL 8.0+、SQL Server、PostgreSQL、Oracle等),这是最简洁高效的方法。我们用ROW_NUMBER()函数按ServiceId分组,再按目标列(第一列)降序排序,这样每个组内数值最大的行排第1,次大的排第2,最后筛选出行号≤2的记录即可:
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY ServiceId ORDER BY ValueColumn DESC) AS row_num FROM TestDeleteTable ) AS temp_table WHERE row_num <= 2;
要是你需要保留同一ServiceId下数值并列最大的所有行(比如有3行数值都是最大的,想全部保留),可以把ROW_NUMBER()换成RANK()或者DENSE_RANK(),这样并列的行都会得到相同的行号,不会被过滤掉:
SELECT * FROM ( SELECT *, RANK() OVER (PARTITION BY ServiceId ORDER BY ValueColumn DESC) AS row_rank FROM TestDeleteTable ) AS temp_table WHERE row_rank <= 2;
方案二:适配不支持窗口函数的旧版数据库
如果你的数据库版本比较旧(比如MySQL 5.x),不支持窗口函数,可以用关联查询的方式实现:
SELECT t1.* FROM TestDeleteTable t1 WHERE ( SELECT COUNT(*) FROM TestDeleteTable t2 WHERE t2.ServiceId = t1.ServiceId AND t2.ValueColumn >= t1.ValueColumn ) <= 2;
这个逻辑是:对每一行,统计同一ServiceId下数值大于等于当前行的行数,只要这个行数≤2,就保留该行,相当于取每个ServiceId下数值最大的前两行。
额外:如果需要删除重复行只保留目标行
要是你最终目的是清理表,删掉不需要的重复行,只保留每个ServiceId下数值最大的两行,以MySQL为例可以这么写(假设表有主键id,没有的话可以用唯一标识列替换):
DELETE t1 FROM TestDeleteTable t1 LEFT JOIN ( SELECT id, ROW_NUMBER() OVER (PARTITION BY ServiceId ORDER BY ValueColumn DESC) AS row_num FROM TestDeleteTable ) AS temp_table ON t1.id = temp_table.id WHERE temp_table.row_num > 2;
内容的提问来源于stack exchange,提问作者Asifuzzaman




