删除每个用户的行和保留N行的eventType

时间:2013-12-23 09:19:57

标签: sql sql-server sql-server-2000

我想删除表中最旧的条目并保留N行。这很简单。

DELETE TOP(1000) from TABLE ORDER BY [date] DESC

但我想删除基于User和EventType的行。因此,如果我们设置N = 50,我想保留每个用户和事件类型的最新50条记录。

我的表格如下:

API_eventLog
- uid (PK, int, not null)
- eventTypeID (FK, int, not null)
- userGUID (FK, uniqueIdentifier, not null)
- date (datetime, not null)
- ...

SO上有一个类似的question,它有以下答案,但不幸的是它适用于SQL Server 2005。

;WITH Dealers AS (
    SELECT *,
    ROW_NUMBER() OVER(PARTITION BY DealerID ORDER BY SomeTimeStamp DESC) RowID
    FROM MyDealersTable
)
DELETE 
FROM Dealers
WHERE RowID > 50

在SQL Server 2000中是否有一个具有良好性能的解决方案?我能想到的只是一个基于游标的解决方案,但这是慢速运行的方法。

示例数据:

[uid]   [EventTypeID]   [userGUID]  [date]
1   1   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-17
2   2   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-17
3   3   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-18
4   4   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-18
5   1   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-19
6   1   5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B    2013-11-22
7   1   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-11-06
8   2   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-11-17
9   3   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-12-01
10  2   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-12-07
11  2   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-12-18
11  1   17941D18-CC79-4C29-BBBA-9CBE60993E43    2013-12-20

在上面的例子中,给定N = 2,我想用[uid] 1和8删除行。(即保留每个User和EventTypeID的2个最新行。

2 个答案:

答案 0 :(得分:1)

以下查询应该模拟SQL Server 2000中的ROW_NUMBER函数。

DELETE API_eventLog
WHERE id IN
  (SELECT 
    id
   FROM API_eventLog AS a1
   WHERE
     (SELECT COUNT(1)
       FROM API_eventLog AS a2
       WHERE a2.userguid = a1.userguid
       AND a2.eventTypeID = a1.eventTypeID
       AND (a2.date > a1.date)) > 0); 
SELECT * FROM API_eventLog;

将0替换为50或您要保留的任何数字或行。

我无法在SQL Server 2000中测试它,但here是SQL Server 2008中的一个工作示例。

修改

似乎我犯了一个小错误。如果您想保留最新的行,则日期检查应为greater than而不是less than。我更新了我的例子。

答案 1 :(得分:0)

抱歉@David我不得不搬家。胺几乎一样。我假设每个eventtypeid日期升序每个userGUID生成一行行号。每个事件的每个userGUID即使在现实生活中也可能没有50行或更多行。那样的话是什么?

Declare @API_eventLog table(uid int,EventTypeID int,userGUID uniqueIdentifier,date1 date)
insert into @API_eventLog
values(1,   1,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-17'),
(2,   2,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-17'),
(3,   3,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-18'),
(4,   4,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-18'),
(5,   1,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-19'),
(6,   1,   '5B1DCB9D-4EC7-4AAE-BEB1-DC1EA90EA06B',    '2013-11-22'),
(7,   1,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-11-06'),
(8,   2,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-11-17'),
(9,   3,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-12-01'),
(10,  2,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-12-07'),
(11,  2,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-12-18'),
(11,  1,   '17941D18-CC79-4C29-BBBA-9CBE60993E43',    '2013-12-20')



Declare @i int=1
--you can test this other sample data
select *  from 
(select *,
(select count(*) from @API_eventLog b where b.userGUID=a.userGUID and a.EventTypeID=b.EventTypeID and b.date1<=a.date1) rn
from @API_eventLog a)t4
where rn<=@i

-- you can perform this
delete  from t4 from
(select *,
(select count(*) from @API_eventLog b where b.userGUID=a.userGUID and a.EventTypeID=b.EventTypeID and b.date1<=a.date1) rn
from @API_eventLog a)t4
where rn<=@i