Mysql SQL删除时间戳早于(现在-x天)的所有行,但保留最近的n条记录除外
如果我有下表,我需要删除所有比现在早-x天的记录,但这些记录不在最近的n个记录中 具体示例:用户不能在90天内重复使用密码,也不能重复使用最后10个密码。如果我每90天更改一次密码,我仍然无法重复使用密码进行10次更改Mysql SQL删除时间戳早于(现在-x天)的所有行,但保留最近的n条记录除外,mysql,sql,Mysql,Sql,如果我有下表,我需要删除所有比现在早-x天的记录,但这些记录不在最近的n个记录中 具体示例:用户不能在90天内重复使用密码,也不能重复使用最后10个密码。如果我每90天更改一次密码,我仍然无法重复使用密码进行10次更改 CREATE TABLE PASSWORD_HISTORY ( ID BIGINT NOT NULL AUTO_INCREMENT, USER_NAME VARCHAR(255) NOT NULL, PASS
CREATE TABLE PASSWORD_HISTORY (
ID BIGINT NOT NULL AUTO_INCREMENT,
USER_NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
SALT VARCHAR(255),
CREATED_TIMESTAMP BIGINT NOT NULL,
UPDATED_TIMESTAMP BIGINT NOT NULL,
TENANT_ID INTEGER DEFAULT -1234,
PRIMARY KEY (ID)
)ENGINE INNODB;
这将只删除ID最低的行,如果这些行属于具有10条以上记录的用户名,并且这些行的创建时间戳超过90天。当然,您应该使用SELECT*来代替DELETE来运行它,以确保它提供了您想要的内容。此外,我将使用Begin事务运行;并准备回滚事务;如果删除时出现问题。如果我理解正确,您希望删除最近的记录超过90天且密码不在最近90天内的记录。我不知道你为什么要删除这些。您可以在查询数据时强制执行这些规则,而不是在数据本身中。如果您愿意,您可以轻松地将规则更改为120天 在任何情况下,如果只为每个用户枚举密码,这将简单得多。但事实并非如此,MySQL也不支持行号。这建议使用变量来枚举结果。由于MySQL的规则,这需要一个子查询和delete中的join。剩下的只是基本的条件逻辑:
delete ph
from password_history ph join
(select ph2.*,
(@rn := if(@u = user_name, @rn + 1,
if(@u := user_name, 1, 1)
)
) as seqnum
from password_history ph2 cross join
(select @rn := 0, @u := '') params
order by user_name, created_timestamp desc
) ph2
on ph2.id = ph.id
where ph2.seqnum > 10 and
ph.created_timestamp <= date_sub(curdate(), interval 90 day)
你能解释一下为什么你有一个更新的时间戳列吗?你发布了一个密码历史记录表,我猜你是用它来存储用户一段时间以来使用过的不同密码的。你是在问如果某个特定用户的行超过x天并且不是最近10天,如何从该表中删除这些行?我不需要更新的\u时间戳…习惯的力量包括在内;我怀疑我会在代码完成之前放弃。按用户名列出的最后n条记录或表中的总共n条记录按用户名列出的最后n条记录我留给您90天的时间。如果您同意结果,则执行删除操作,其中deleteMe=2。。。并改变表格,删除该列
DELETE
FROM PASSWORD_HISTORY
Where PASSWORD_HISTORY.ID Not IN
(
SELECT ID FROM(SELECT pass1.[USER_NAME], Count(*) num, pass1.ID
FROM Password_History pass1 JOIN Password_History pass2
ON pass1.[USER_NAME] = pass2.[USER_NAME] AND pass1.ID <= pass2.ID
Group BY pass1.[USER_NAME], pass1.ID
Having Count(*) <= 10
) a
)
AND CREATED_TIMESTAMP <= Convert(int, DATEADD(day, -90, GetDate()))
delete ph
from password_history ph join
(select ph2.*,
(@rn := if(@u = user_name, @rn + 1,
if(@u := user_name, 1, 1)
)
) as seqnum
from password_history ph2 cross join
(select @rn := 0, @u := '') params
order by user_name, created_timestamp desc
) ph2
on ph2.id = ph.id
where ph2.seqnum > 10 and
ph.created_timestamp <= date_sub(curdate(), interval 90 day)