我正在使用MS SQL数据库,我有一个名为" Logs"看起来像这样:
这里一个接一个地添加记录,所以几天/几周之后桌子会变得很大。
我需要定期做的是稍微清理一下。即我需要一个SQL查询来删除旧行,并且只保留此表中最近的100条记录。
我同意最好让它删除早于some_date的记录&#34; ...之前就是这样,但客户希望它不同:(所以......我们在这里。< / p> 顺便说一句:我对那些对这个问题不屑一顾的人感到有些失望。它有什么问题或者是什么?... 想象一下:这个问题产生了4个答案! ......一个人决定对此投反对票!现在我真的不知道该怎么想......周围的人很奇怪:(
答案 0 :(得分:6)
您可以使用以下其中一项:
-- 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
)
答案 1 :(得分:3)
虽然我同意其他人认为这可能不是一条路,但无论如何,这是一种方法:
;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] )
答案 2 :(得分:3)
不要使用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
);
答案 3 :(得分:1)
这对我有用:
;with cte as(select top(select count(*) - 100 from table) * from table order by dt)
delete from cte
答案 4 :(得分:0)
DECLARE @cutoff DATETIME
SELECT TOP 100 @cutoff = [DateTime] FROM Logs ORDER BY [DateTime] DESC
DELETE FROM Logs WHERE [DateTime] < @cutoff