SQL如何按教室分组,实现每个分组内学生ID去重?
按教室维度实现学生ID去重的SQL方案
你的需求本质是把去重粒度从全局学生ID,调整为教室编号+学生ID的组合维度:只要两个字段的组合不重复,就视为有效记录,允许不同教室出现相同学生ID。
查询时返回去重结果(不修改原表)
基础去重(不指定保留哪条时间记录)
直接对去重维度的字段组合使用DISTINCT即可,注意不要把时间字段放进DISTINCT的判定逻辑里,否则不同时间的同教室同学生记录还是会被保留:
SELECT DISTINCT 教室编号, 学生ID FROM School;
如果需要同时带出时间字段,且要保留符合规则的单条记录(比如最早/最晚进入教室的时间),用GROUP BY搭配聚合函数实现:
-- 保留每个学生在对应教室最早的进入记录 SELECT 教室编号, 学生ID, MIN(时间字段) AS 进入时间 FROM School GROUP BY 教室编号, 学生ID;
把MIN替换为MAX,即可保留每个学生最晚的进入记录。
清理原表中的重复数据(永久删除冗余条目)
如果需要直接删除表内的重复数据,仅保留每个教室内每个学生的唯一记录,分两种情况写SQL:
支持窗口函数的数据库(MySQL8.0+、PostgreSQL、SQL Server等)
用ROW_NUMBER()给重复记录打标后删除即可:
WITH mark_duplicate AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY 教室编号, 学生ID ORDER BY 时间字段 ASC -- 按时间升序排序,最早进入的记录序号为1,其余重复项序号大于1 ) AS rn FROM School ) DELETE FROM School WHERE (教室编号, 学生ID, 时间字段) IN ( SELECT 教室编号, 学生ID, 时间字段 FROM mark_duplicate WHERE rn > 1 );
低版本MySQL(不支持窗口函数)
通过表自连接删除重复项,以下写法会保留同教室同学生最早的进入记录,删除其余重复条目:
DELETE s1 FROM School s1 INNER JOIN School s2 ON s1.教室编号 = s2.教室编号 AND s1.学生ID = s2.学生ID AND s1.时间字段 > s2.时间字段;
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

