SQL Server如何删除重复条目 仅保留最新时间的最后一条记录
SQL Server 表分组保留最新时间记录的删除实现方案
适配场景:同一业务匹配条目对应多条事件记录,仅需保留每组中时间值最大(即你提到的最新时间1800对应的行),删除其余冗余历史记录,所有操作可在SSMS中直接执行。
方案1:窗口函数标记法(适配SQL Server 2008及以上所有版本,通用性最强)
第一步:先做删除前校验,避免误删
执行以下查询,确认被标记为待删除的行范围是否正确:SELECT *, -- 按业务判定的“同一条目”维度分组,按时间倒序给组内行排序 ROW_NUMBER() OVER ( PARTITION BY 用于判定同一条目的字段1, 用于判定同一条目的字段2 ORDER BY 时间值字段 DESC ) AS row_rank FROM 你的目标表名筛选结果中
row_rank > 1的行,就是所有非最新时间的冗余记录,逐行核对确认没有把需要保留的1800时间行纳入删除范围后,再执行下一步。第二步:正式执行删除
;WITH ranked_records AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY 用于判定同一条目的字段1, 用于判定同一条目的字段2 ORDER BY 时间值字段 DESC ) AS row_rank FROM 你的目标表名 ) DELETE FROM ranked_records WHERE row_rank > 1 -- 仅保留每组内排第1的最新时间行
方案2:最大时间关联法(适配无窗口函数支持的老旧SQL Server版本)
- 第一步:先校验待删除范围
核对校验结果无误后,执行删除:SELECT t.* FROM 你的目标表名 t INNER JOIN ( -- 按条目维度统计每组的最大时间值 SELECT 用于判定同一条目的字段1, 用于判定同一条目的字段2, MAX(时间值字段) AS max_time FROM 你的目标表名 GROUP BY 用于判定同一条目的字段1, 用于判定同一条目的字段2 ) latest_record ON t.用于判定同一条目的字段1 = latest_record.用于判定同一条目的字段1 AND t.用于判定同一条目的字段2 = latest_record.用于判定同一条目的字段2 AND t.时间值字段 < latest_record.max_time -- 比本组最大时间小的行,即为冗余待删行DELETE t FROM 你的目标表名 t INNER JOIN ( SELECT 用于判定同一条目的字段1, 用于判定同一条目的字段2, MAX(时间值字段) AS max_time FROM 你的目标表名 GROUP BY 用于判定同一条目的字段1, 用于判定同一条目的字段2 ) latest_record ON t.用于判定同一条目的字段1 = latest_record.用于判定同一条目的字段1 AND t.用于判定同一条目的字段2 = latest_record.用于判定同一条目的字段2 AND t.时间值字段 < latest_record.max_time
操作注意事项
- 执行删除前务必开启事务兜底:在删除语句前加上
BEGIN TRANSACTION;,删除执行完成后先查询表内剩余数据确认符合预期,再执行COMMIT;提交修改,若发现范围错误直接执行ROLLBACK;回滚,避免不可逆的数据丢失。 - 替换代码内的占位内容:将“用于判定同一条目的字段”替换为实际业务中判断“属于同一个条目”的全部字段,将“时间值字段”替换为实际存储1800这类时间标记的字段名,将“你的目标表名”替换为实际操作的表名。
- 如果存在同一分组下多条记录时间值均为1800的场景,把方案1中的
ROW_NUMBER()替换为RANK(),即可将同时间的所有记录全部保留,不会误删。
内容的提问来源于stack exchange,提问作者ZZBeard
相关产品推荐
相关产品推荐

