t-sql查询:检索最新的行方法

时间:2010-09-07 23:25:29

标签: sql sql-server tsql sql-server-2008

基于下表

Table_A

ID   Rev  Description
-----------------------------------
1    1    Some text.
1    2    Some text. Adding more.
1    3    Some text. Ading more & more.

以上将在用户更新说明时继续添加新行。

我想用MAX(Rev)取行[即最新描述]。

为此,我执行以下操作:

;with AllDescriptions As
(
 select 
        ID
        , Rev
        , Description 
        , ROW_NUMBER() over (partition by ID order by Rev desc) as RowNum
        from Table_A
        Where ID = 1
)
select ID, Rev, Description from AllDescription
where RowNum = 1

最近我看到了获得相同结果的不同方法

select b.* from 
(
 select ID, MAX(Rev) as MaxRev 
 from Table_A 
 where ID = 1
 group by ID
) as a
inner join 
(
 select ID, Rev, Description from Table_A where ID = 1
) as b
on a.ID = b.ID and a.MaxRev = b.Rev

从学习的角度来看,我想知道以上两种方法中的哪一种更好?或者,如果有更好的方法来做同样的事情?

3 个答案:

答案 0 :(得分:1)

第二种方法在引入Row_Number()之前看起来像SQL Server 2000方法。这是Greatest-n-per-group problem

要评估它们,您应该运行SET STATISTICS IO ON

来查看执行计划和I / O统计信息

当然,对于您给出以下内容的具体示例,同样可以正常工作

 select TOP 1
        ID
        , Rev
        , Description 
        from Table_A
        Where ID = 1
ORDER BY Rev desc

答案 1 :(得分:1)

如果您的父表只列出了一次ID,那么这有时可能优于其他策略,包括row_number解决方案:

SELECT
   X.*
FROM
   ParentTable P
   CROSS APPLY (
      SELECT TOP 1 *
      FROM Table_A A
      WHERE P.ID = A.ID
      ORDER BY A.Rev DESC
   ) X

疯狂的,专利的(只是开玩笑),单扫描魔术查询,通常也可以胜过其他方法:

SELECT
   ID,
   Rev = Convert(int, Substring(Packed, 1, 4)),
   Description = Convert(varchar(100), Substring(Packed, 5, 100))
FROM
   (
      SELECT
         ID,
         Packed = Max(Convert(binary(4), Rev) + Convert(varbinary(100), Description))
      FROM Table_A
      GROUP BY ID
   ) X

注意:不推荐使用最后一种方法,但模拟MS Access中的First / Last聚合很有趣。

答案 2 :(得分:0)

我倾向于赞成第一种方法 - 从可读性的角度来看,一旦你对ROW_NUMBER()OVER ...语法感到满意,那么它就会更具可读性。从表现的角度来看,如果两者之间存在很大差异,我会感到惊讶 - 如果有的话,那么我会期望第二种表现会更差 - 但我会立即予以纠正!