You can do this with row_number()
:
select t.*
from (select t.*,
row_number() over (partition by PlayerId, EndDate
order by lastupdate desc, registrationid desc
) as seqnum
from table t
) t
where EndDate is not NULL or seqnum = 1;
This enumerates the rows in a group. In this case, the group is defined by the PlayerId
, EndDate
combination. So, all the NULL
values for a player are in one group. The first value is the one with the highest lastupdate
date and then the highest registration id. The outer where
takes all records that either have a valid EndDate
or that are first in the group.
Your question is a little ambiguous on whether you just want to return these values or if you want to actually delete the others. Fortunately, SQL Server has updatable CTEs, so you can use very similar logic to delete the records from the table:
with todelete as (
select t.*,
row_number() over (partition by PlayerId, EndDate
order by lastupdate desc, registrationid desc
) as seqnum
from table t
) t
delete from todelete
where EndDate is NULL and seqnum > 1;