为每个实体选择前N个记录

时间:2016-06-24 06:58:03

标签: sql sql-server sql-server-2008-r2 database-administration

我有一个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

现在,我想要top 1 row基于date column每个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来处理它,但是想用简单的查询来做。

**************** EDIT **************************

'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

他在评论中提到了这一点,并将其添加到问题中,以便没有人遗漏它。

5 个答案:

答案 0 :(得分:6)

使用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

答案 1 :(得分:0)

如果您不能使用分析功能,例如因为您的应用程序层不允许它,那么您可以尝试使用子查询来得到答案的以下解决方案:

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

答案 2 :(得分:0)

您也可以尝试使用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

答案 3 :(得分:0)

Select * from DEVICE_TABLE D 
where [Reported Date] = (Select Max([Reported Date]) from DEVICE_TABLE where Device_ID = D.Device_ID)

应该做的伎俩,假设"基于日期列的前1行"意味着您要选择每个Device_ID的最新报告日期?

对于您的标题,请选择每个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个日期...

答案 4 :(得分:0)

同样没有分析功能,您可以使用CROSS APPLY:

# Read in our configuration
if [ -z "${BOOTUP:-}" ]; then
    if [ -f /etc/sysconfig/init ]; then
        . /etc/sysconfig/init
    else
        # verbose ->> very (very!) old bootup look (prior to RHL-6.0?)
        # color ->> default bootup look
        # other ->> default bootup look without ANSI colors or positioning
        BOOTUP=color
        # Column to start "[  OK  ]" label in:
        RES_COL=60
        # terminal sequence to move to that column:
        MOVE_TO_COL="echo -en \\033[${RES_COL}G"
        # Terminal sequence to set color to a 'success' (bright green):
        SETCOLOR_SUCCESS="echo -en \\033[1;36m"
        # Terminal sequence to set color to a 'failure' (bright red):
        SETCOLOR_FAILURE="echo -en \\033[1;31m"
        # Terminal sequence to set color to a 'warning' (bright yellow):
        SETCOLOR_WARNING="echo -en \\033[1;33m"
        # Terminal sequence to reset to the default color:
        SETCOLOR_NORMAL="echo -en \\033[0;39m"

        # Verbosity of logging:
        LOGLEVEL=1
    fi
    if [ "$CONSOLETYPE" = "serial" ]; then
        BOOTUP=serial
        MOVE_TO_COL=
        SETCOLOR_SUCCESS=
        SETCOLOR_FAILURE=
        SETCOLOR_WARNING=
        SETCOLOR_NORMAL=
    fi

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

请转到wBob来回答此问题here