SQL select 最近 15 行,但每个用户不超过 3 行

SQL select 15 most recent rows but no more than 3 per user

假设我有以下 table:

CREATE TABLE test_UserAds
(
    UserId int,
    Title varchar(255),
    ActivateDate DATETIME2
);

而这个测试数据:

INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 1, 'Waiter', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 1, 'Policeman', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 1, 'Data Clerk', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 1, 'Nurse', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Chef', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Teacher', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Mechanic', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Cleaner', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Painter', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Bricklayer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Plasterer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 2, 'Electrician', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Programmer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Driver', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Photographer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Carpenter', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'CEO of some nasty Corporation', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Writer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Labourer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 3, 'Stack Overflow Bore', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Surgeon', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Diver', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Chicken sexer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Bottle washer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Food Tester', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Chemist', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Biologist', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 4, 'Secretary', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Doctor', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Developer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Designer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Tramp', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Clock watcher', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Pedant', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Neuromancer', SYSDATETIME())
INSERT INTO dbo.test_UserAds ( UserId, Title, ActivateDate ) VALUES  ( 5, 'Gardener', SYSDATETIME())

我希望能够 return 按 ActivateDate (desc) 排序的前 15 行,但每个用户不超过 3 行。谁能推荐一下?

预期的结果集如下所示:

1, Waiter
1, Policeman
1, Data Clerk
2, Chef
2, Teacher
2, Mechanic
3, Programmer
3, Driver,
3, Photographer
4, Surgeon
4, Diver
4, Chicken sexer
5, Doctor
5, Developer
5, Designer

在SQL服务器中,您可以使用row_Number()为每个用户获取最近的三个。然后取最近的 15 个:

select top 15 ua.*
from (select ua.*,
             row_number() over (partition by userid order by activatedate desc) as seqnum
      from dbo.test_UserAds ua
     ) ua
where seqnum <= 3  -- get three most recent for each user
order by activatedate desc;

如果您有 table 个用户,您还可以:

select top 15 ua.*
from users u cross apply
     (select top 3 ua.*
      from dbo.test_UserAds ua
      where ua.userid = u.userid
      order by activatedate desc
     ) ua
order by activatedate desc;