T-SQL查询:仅选择最近的行(对于每个计算机名称)

时间:2014-04-11 14:23:48

标签: sql tsql

我在SQL Server 2014 Developer Edition数据库中有一个名为ComputerStatus的表,如下所示:

ComputerName       Status          Timestamp
------------       -----------     ------------
client01           Online          2013-04-11 11:00 AM
client01           Online          2013-04-08 10:00 AM
client01           Offline         2013-04-05 09:00 PM
client02           Offline         2013-04-08 10:00 AM
client02           Online          2013-04-03 10:00 AM
client03           Online          2013-04-02 10:00 AM
client03           Offline         2013-04-05 10:00 PM
client03           Online          2013-04-03 12:00 PM

我想要做的是获取每个唯一计算机名称的最新行(基于Timestamp)行。虽然我对SQL Server查询非常讨厌,但我知道我可以:

  • 编写一个存储过程,检索最新的条目(对于一台计算机),然后使用游标多次调用该过程
  • 使用以下T-SQL代码(在存储过程中)检索最新行:select top 1 * from ComputerStatus where ComputerName = 'client01' order by Timestamp descending

期望结果

ComputerName       Status          Timestamp
------------       -----------     ------------
client01           Online          2013-04-11 11:00 AM
client02           Offline         2013-04-08 10:00 AM
client03           Offline         2013-04-05 10:00 PM

我知道如何选择单台计算机的最新行。我正在努力解决的部分是如何为表中所有独特的计算机执行此操作。这是否需要我使用SQL游标来迭代表中的唯一计算机名称?或者,是否有更有效的方法来实现这些结果?

2 个答案:

答案 0 :(得分:9)

您可以使用RowNumber执行此操作,RowNumber为每一行提供行号。由于您希望基于TimeStamp为每个computerName提供从1开始的行号,我们需要通过Computername对其进行分区

select * from (
select *, ROW_NUMBER() over (partition by ComputerName order by Timestamp desc) as rno 
from ComputerStatus
) as T where rno = 1

MSDN

答案 1 :(得分:3)

另一种选择是这样的:

    SELECT cs1.*
    FROM ComputerStatus cs1
      INNER JOIN (SELECT ComputerName, MAX(Timestamp) as [Timestamp] 
                  FROM ComputerStatus
                  GROUP BY ComputerName) cs2
      ON cs1.ComputerName=cs2.ComputerName and cs1.Timestamp = cs2.Timestamp

子查询将查找计算机名称和最新时间​​戳,然后外部查询将使用该数据并将其与状态匹配。

但我更喜欢使用ROW_NUMBER()。太方便了!