删除除最近 100 行以外的所有行
Delete all rows except 100 most recent ones
我正在使用 MS SQL 数据库,我有一个名为 "Logs" 的 table,如下所示:
一条条记录在这里添加,所以 table 变得相当大 days/weeks。
我需要定期做的是一些清理工作。 IE。我需要一个 SQL 查询,该查询将删除旧行并仅保留此 table.
中最近的 100 条记录
我同意最好有它"delete records older than some_date"...以前是这样的,但是客户想要不同的:(所以...我们到了。
顺便说一句:我对人们对这个问题持否定态度感到有点失望。有什么不对吗?... 想象一下:这个问题已经产生了4个答案! ... 一个人决定对此表示否定!现在我真的不知道怎么想了...这附近的陌生人:(
虽然我同意其他人的意见,这可能不是要走的路,但这里有一个方法可以做到:
;WITH keepers AS
( SELECT TOP 100 [DateTime]
FROM dbo.Logs
ORDER BY [DateTime] DESC )
DELETE FROM dbo.Logs a
WHERE NOT EXISTS ( SELECT 1 FROM keepers b WHERE b.[DateTime] = a.[DateTime] )
您可以使用以下之一:
-- offset clause
WITH goners AS (
SELECT *
FROM Logs
ORDER BY DateTime DESC
OFFSET 100 ROWS
)
DELETE FROM goners
-- numbered rows
WITH goners AS (
SELECT ROW_NUMBER() OVER(ORDER BY DateTime DESC) AS rn, Logs.*
FROM Logs
)
DELETE FROM goners
WHERE rn > 100
-- nth value
-- note that this "keeps" all rows that tie for last place
DELETE FROM Logs
WHERE DateTime < (
SELECT MIN(DateTime)
FROM (
SELECT TOP 100 DateTime
FROM Logs
ORDER BY DateTime DESC
) AS x
)
不要使用 NOT EXISTS
,只需使用 >=
:
WITH keepers AS (
SELECT TOP 100 [DateTime]
FROM dbo.Logs
ORDER BY [DateTime] DESC
)
DELETE FROM dbo.Logs a
WHERE l.DateTime < (SELECT MIN([DateTime]) FROM keepers);
我不确定 delete
是 运行 时是否有可以添加新行的锁定设置。如果是这样,这仍然是安全的。
您实际上可以在 SQL Server 2012+ 中简化此操作:
DELETE FROM dbo.Logs a
WHERE l.DateTime < (SELECT [DateTime]
FROM dbo.logs
ORDER BY [DateTime]
OFFSET 99 FETCH FIRST 1 ROW ONLY
);
DECLARE @cutoff DATETIME
SELECT TOP 100 @cutoff = [DateTime] FROM Logs ORDER BY [DateTime] DESC
DELETE FROM Logs WHERE [DateTime] < @cutoff
这对我有用:
;with cte as(select top(select count(*) - 100 from table) * from table order by dt)
delete from cte
我正在使用 MS SQL 数据库,我有一个名为 "Logs" 的 table,如下所示:
一条条记录在这里添加,所以 table 变得相当大 days/weeks。
我需要定期做的是一些清理工作。 IE。我需要一个 SQL 查询,该查询将删除旧行并仅保留此 table.
中最近的 100 条记录我同意最好有它"delete records older than some_date"...以前是这样的,但是客户想要不同的:(所以...我们到了。
顺便说一句:我对人们对这个问题持否定态度感到有点失望。有什么不对吗?... 想象一下:这个问题已经产生了4个答案! ... 一个人决定对此表示否定!现在我真的不知道怎么想了...这附近的陌生人:(
虽然我同意其他人的意见,这可能不是要走的路,但这里有一个方法可以做到:
;WITH keepers AS
( SELECT TOP 100 [DateTime]
FROM dbo.Logs
ORDER BY [DateTime] DESC )
DELETE FROM dbo.Logs a
WHERE NOT EXISTS ( SELECT 1 FROM keepers b WHERE b.[DateTime] = a.[DateTime] )
您可以使用以下之一:
-- offset clause
WITH goners AS (
SELECT *
FROM Logs
ORDER BY DateTime DESC
OFFSET 100 ROWS
)
DELETE FROM goners
-- numbered rows
WITH goners AS (
SELECT ROW_NUMBER() OVER(ORDER BY DateTime DESC) AS rn, Logs.*
FROM Logs
)
DELETE FROM goners
WHERE rn > 100
-- nth value
-- note that this "keeps" all rows that tie for last place
DELETE FROM Logs
WHERE DateTime < (
SELECT MIN(DateTime)
FROM (
SELECT TOP 100 DateTime
FROM Logs
ORDER BY DateTime DESC
) AS x
)
不要使用 NOT EXISTS
,只需使用 >=
:
WITH keepers AS (
SELECT TOP 100 [DateTime]
FROM dbo.Logs
ORDER BY [DateTime] DESC
)
DELETE FROM dbo.Logs a
WHERE l.DateTime < (SELECT MIN([DateTime]) FROM keepers);
我不确定 delete
是 运行 时是否有可以添加新行的锁定设置。如果是这样,这仍然是安全的。
您实际上可以在 SQL Server 2012+ 中简化此操作:
DELETE FROM dbo.Logs a
WHERE l.DateTime < (SELECT [DateTime]
FROM dbo.logs
ORDER BY [DateTime]
OFFSET 99 FETCH FIRST 1 ROW ONLY
);
DECLARE @cutoff DATETIME
SELECT TOP 100 @cutoff = [DateTime] FROM Logs ORDER BY [DateTime] DESC
DELETE FROM Logs WHERE [DateTime] < @cutoff
这对我有用:
;with cte as(select top(select count(*) - 100 from table) * from table order by dt)
delete from cte