删除30天前数据但保留唯一用户行的SQL问题排查
问题分析与解决
你的SQL每次执行都有新行被影响,核心原因是逻辑没有完全匹配需求:
- 原SQL仅删除多行用户中超30天的旧行,但随着时间流逝,多行用户里原本未到30天的旧行,会逐渐满足
created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)的条件,因此每次执行都会有这类行被删除。 - 另外,原SQL没有实现“多行用户仅保留最新行”的核心要求——不管旧行是否超30天,只要不是该用户的最新行,都应该直接删除,而非等它们过期再处理。
正确SQL方案(完全匹配需求)
如果你的需求是:每个用户仅保留最新一行(无论是否超30天),其他所有行全部删除(自动覆盖“单用户保留唯一行”的规则),可以用以下高效的JOIN写法:
DELETE e FROM elos_old e LEFT JOIN ( SELECT username, MAX(created_at) AS latest_created FROM elos_old GROUP BY username ) AS latest ON e.username = latest.username AND e.created_at = latest.latest_created WHERE latest.username IS NULL;
逻辑说明
- 子查询
latest先找出每个username对应的最新创建时间。 - 通过左连接,匹配出所有属于“非最新行”的数据(即
latest.username IS NULL的行)。 - 直接删除这些非最新行,确保每个用户仅保留最新的一行。
备选方案(仅删除超30天的非最新行)
如果你的真实需求是:仅删除超30天的行,但单用户的行和多用户的最新行即使超30天也保留,可以用以下SQL:
DELETE FROM elos_old WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY) AND (username, created_at) NOT IN ( SELECT username, MAX(created_at) FROM elos_old GROUP BY username );
逻辑说明
- 筛选出所有超30天的行。
- 排除其中属于每个用户最新行的数据,仅删除超30天的旧行。
注意:这个方案仍会随着时间推移,持续删除刚进入30天过期范围的旧行,这是符合需求的正常现象。
内容的提问来源于stack exchange,提问作者M A
相关产品推荐
相关产品推荐

