如何删除MARK_TABLE中STUDENT、COURSE、SCORE重复的行?
删除MARK_TABLE中的重复行(按STUDENT/COURSE/SCORE去重)
嘿,我来帮你搞定这个重复行删除的问题!你的需求是保留每组STUDENT、COURSE、SCORE完全相同的数据中的一行,删掉其他重复项对吧?下面给你几种不同数据库都适用的方案,你可以根据自己用的数据库选择:
方法1:使用窗口函数(推荐,适用于MySQL 8+、SQL Server、Oracle等)
这种方法用ROW_NUMBER()窗口函数给每组重复数据编号,然后删除编号大于1的行(也就是除了每组里第一行之外的重复行):
WITH DuplicateRows AS ( SELECT ID, -- 按STUDENT/COURSE/SCORE分组,每组内按ID排序,给行编号 ROW_NUMBER() OVER (PARTITION BY STUDENT, COURSE, SCORE ORDER BY ID) AS rn FROM MARK_TABLE ) -- 删除编号大于1的重复行 DELETE FROM DuplicateRows WHERE rn > 1;
验证步骤(非常重要!)
在执行删除前,先把DELETE改成SELECT *,确认要删除的行是不是你想删的:
WITH DuplicateRows AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY STUDENT, COURSE, SCORE ORDER BY ID) AS rn FROM MARK_TABLE ) SELECT * FROM DuplicateRows WHERE rn > 1;
方法2:关联子查询(适用于所有支持JOIN的数据库,比如老版本MySQL)
如果你的数据库不支持CTE或者窗口函数,可以用自关联的方式,删除每组中ID更大的重复行:
-- 删除重复行,保留每组中ID最小的那一行 DELETE t1 FROM MARK_TABLE t1 JOIN MARK_TABLE t2 ON t1.STUDENT = t2.STUDENT AND t1.COURSE = t2.COURSE AND t1.SCORE = t2.SCORE AND t1.ID > t2.ID;
同样,先验证要删除的行:
SELECT t1.* FROM MARK_TABLE t1 JOIN MARK_TABLE t2 ON t1.STUDENT = t2.STUDENT AND t1.COURSE = t2.COURSE AND t1.SCORE = t2.SCORE AND t1.ID > t2.ID;
补充说明
你之前用的INTERSECT语句确实能得到去重后的STUDENT/COURSE/SCORE组合,但因为缺少ID字段,没法直接用来定位要删除的行。上面的两种方法都是基于ID来区分重复行,保留每组里的一行(这里是保留ID最小的,如果你想保留ID最大的,把ORDER BY ID改成ORDER BY ID DESC,或者把t1.ID > t2.ID改成t1.ID < t2.ID就行)。
注意:执行删除操作前,一定要先备份数据,避免误删!
内容的提问来源于stack exchange,提问作者Nicole
相关产品推荐
相关产品推荐

