select 每个实体的前 N ​​条记录

select top N records for each entity

我有一个 table 如下 -


ID   |  Reported Date                  | Device_ID
-------------------------------------------
1    | 2016-03-09 09:08:32.827         | 1
2    | 2016-03-08 09:08:32.827         | 1
3    | 2016-03-08 09:08:32.827         | 1
4    | 2016-03-10 09:08:32.827         | 2
5    | 2016-03-05 09:08:32.827         | 2

现在,我想要一个基于 date columntop 1 row 每个 device_ID

预期输出


ID   |  Reported Date                  | Device_ID
-------------------------------------------
1    | 2016-03-09 09:08:32.827         | 1
4    | 2016-03-10 09:08:32.827         | 2

我正在使用 SQL Server 2008 R2。我可以去写 Stored Procedure 来处理它,但想用简单的查询来完成。

******************编辑***************************

'Felix Pamittan' 的回答效果很好,但 'N' 只需将其更改为

SELECT
    Id, [Reported Date], Device_ID
FROM (
    SELECT *,
        Rn = ROW_NUMBER() OVER(PARTITION BY Device_ID ORDER BY [ReportedDate] DESC)
    FROM tbl
)t
WHERE Rn >= N

他在评论中提到了这一点,想将其添加到问题中,以免有人错过。

使用ROW_NUMBER:

SELECT
    Id, [Reported Date], Device_ID
FROM (
    SELECT *,
        Rn = ROW_NUMBER() OVER(PARTITION BY Device_ID ORDER BY [ReportedDate] DESC)
    FROM tbl
)t
WHERE Rn = 1

如果您不能使用分析函数,例如因为您的应用层不允许,那么您可以尝试以下使用子查询得出答案的解决方案:

SELECT t1.ID, t2.maxDate, t1.Device_ID
INNER JOIN
(
    SELECT Device_ID, MAX([Reported Date]) AS maxDate
    FROM yourTable
    GROUP BY Device_ID
) t2
    ON t1.Device_ID = t2.Device_ID AND t1.[Reported Date] = t2.maxDate

您也可以尝试使用 CTE

With DeviceCTE AS
(SELECT *, ROW_NUMBER() OVER(PARTITION BY Device_ID ORDER BY [Reported Date] DESC) AS Num
 FROM tblname)
 SELECT Id, [Reported Date], Device_ID
 From DeviceCTE
 Where Num = 1
Select * from DEVICE_TABLE D 
where [Reported Date] = (Select Max([Reported Date]) from DEVICE_TABLE where Device_ID = D.Device_ID)

应该可以解决问题,假设 "top 1 row based on date column" 意味着您想要 select 每个 Device_ID 的最新报告日期?

至于你的标题,select 每个 Device_ID

的前 5 行
Select * from DEVICE_TABLE D 
where [Reported Date] in (Select top 5 [Reported Date] from DEVICE_TABLE D  where Device_ID =  D.Device_ID)
order by Device_ID, [Reported Date] desc

将为您提供每个设备 ID 的前 5 个最新报告。 如果您的数据不符合顺序,您可能需要整理出前 5 个日期...

再次没有分析功能,您可以使用 CROSS APPLY :

DECLARE @tbl TABLE(Id INT,[Reported Date] DateTime , Device_ID INT)
 
INSERT INTO @tbl
VALUES 
(1,'2016-03-09 09:08:32.827',1),
(2,'2016-03-08 09:08:32.827',1),
(3,'2016-03-08 09:08:32.827',1),
(4,'2016-03-10 09:08:32.827',2),
(5,'2016-03-05 09:08:32.827',2)


SELECT r.*
FROM ( SELECT DISTINCT Device_ID FROM @tbl ) d
    CROSS APPLY ( SELECT TOP 1 * 
                  FROM @tbl t 
                  WHERE d.Device_ID = t.Device_ID ) r

可以轻松修改以支持N条记录。

感谢 wBob 回答了这个问题 here