Question

I want to delete the oldest entries in a table and keep N rows. This is fairly simple to do.

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

But I want to delete rows based on User and EventType. So if we set N=50, I want to keep the newest 50 records per User and EventType.

My Table looks like this:

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

There is a similar question already on SO that has the following answer, but unfortunately it is for 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

Is there a solution to this in SQL server 2000 with good performance? All I can think of myself is a cursor-based solution but that is way to slow run be executed frequently.

Example Data:

[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

In above example, given N=2, I would like to delete row with [uid] 1 and 8. (ie keeping the 2 newest rows per User and EventTypeID.

Was it helpful?

Solution

The following query should simulate the ROW_NUMBER function in SQL Server 2000.

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;

Replace the 0 by 50 or whatever number or rows you want to keep.

I can't test it in SQL Server 2000, but here is a working example in SQL Server 2008.

EDIT:

Seems like I made a small mistake. The date check should be greater than instead of less than if you want to keep the newest rows. I updated my example.

OTHER TIPS

sorry @David i had to move then.mine is almost same. i have assume generate row number per userGUID per eventtypeid date ascending.also each userGUID per event may not have 50 or more rows even in real life.In that case what ?

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top