从数据库中检索每个组中的最后一条记录 - SQL Server 2005/2008

Rya*_*anF 22 t-sql sql-server-2005 distinct sql-server-2008

我做了一些搜索似乎无法得到我正在寻找的结果.基本上我们在整个公司都有四种不同的管理系统,我正在定期组合每个系统的所有数据.我的目标是每小时将数据更新到一个中央数据库.这是我正在使用的示例数据集:

COMPUTERNAME | SERIALNUMBER | USERNAME | LASTIP | LASTUPDATE | SOURCE
TEST1 | 1111 | BOB | 1.1.1.1 | 1/17/2011 01:00:00 | MGMT_SYSTEM_1
TEST1 | 1111 | BOB | 1.1.1.1 | 1/18/2011 01:00:00 | MGMT_SYSTEM_2
TEST1 | 1111 | PETER | 1.1.1.11 | 1/19/2011 01:00:00 | MGMT_SYSTEM_3
TEST2 | 2222 | GEORGE | 1.1.1.2 | 1/17/2011 01:00:00 | MGMT_SYSTEM_1
TEST3 | 3333 | TOM | 1.1.1.3 | 1/19/2011 01:00:00 | MGMT_SYSTEM_2
TEST4 | 4444 | MIKE   | 1.1.1.4 | 1/17/2011 01:00:00 | MGMT_SYSTEM_1
TEST4 | 4444 | MIKE   | 1.1.1.41 | 1/19/2011 01:00:00 | MGMT_SYSTEM_3
TEST5 | 5555 | SUSIE  | 1.1.1.5 | 1/19/2011 01:00:00 | MGMT_SYSTEM_1
Run Code Online (Sandbox Code Playgroud)

所以我想查询这个主表,只检索最新记录(基于LASTUPDATE),这样我就可以获得有关该系统的最新信息.问题是每个数据库中可能有一个系统,但当然它们永远不会有相同的更新时间.

我希望得到这样的东西:

TEST1 | 1111 | PETER | 1.1.1.11 | 1/19/2011 01:00:00 | MGMT_SYSTEM_3
TEST2 | 2222 | GEORGE | 1.1.1.2 | 1/17/2011 01:00:00 | MGMT_SYSTEM_1
TEST3 | 3333 | TOM | 1.1.1.3 | 1/19/2011 01:00:00 | MGMT_SYSTEM_2
TEST4 | 4444 | MIKE   | 1.1.1.41 | 1/19/2011 01:00:00 | MGMT_SYSTEM_3
TEST5 | 5555 | SUSIE  | 1.1.1.5 | 1/19/2011 01:00:00 | MGMT_SYSTEM_1
Run Code Online (Sandbox Code Playgroud)

我尝试过使用MAX函数,但是我只能检索一列.而且我不能在子查询中使用它,因为我没有唯一的ID字段可以给我最后更新的记录.其中一个系统是一个MySQL数据库,MySQL中的MAX函数实际上会以我需要的方式工作,每个GROUP BY只返回一条记录,但它在SQL Server中不起作用.

我想我需要使用MAX和LEFT JOIN,但到目前为止我的尝试都失败了.

非常感谢您的帮助.在过去的3-4个小时里,我一直绞尽脑汁试图获得有效的查询.此主表位于SQL Server 2005服务器上.

谢谢!

Joe*_*lli 59

;with cteRowNumber as (
    select COMPUTERNAME, SERIALNUMBER, USERNAME, LASTIP, LASTUPDATE, SOURCE,
           row_number() over(partition by COMPUTERNAME order by LASTUPDATE desc) as RowNum
        from YourTable
)
select COMPUTERNAME, SERIALNUMBER, USERNAME, LASTIP, LASTUPDATE, SOURCE
    from cteRowNumber
    where RowNum = 1
Run Code Online (Sandbox Code Playgroud)

  • 当您的表有数千行时,这是一个非常慢的查询 (3认同)

Gor*_*off 12

在SQL Server中,性能最高的解决方案通常是相关的子查询:

select t.*
from t
where t.lastupdate = (select max(t2.lastupdate)
                      from t t2
                      where t2.computername = t.computername
                     );
Run Code Online (Sandbox Code Playgroud)

特别是,这可以利用索引(computername, lastupdate).从概念上讲,这比这更快的原因row_number()是因为此查询只是过滤掉了不匹配的行.该row_number()版本需要附加到行号都行,它过滤之前-也就是更多的数据处理.