从表中返回一组最近的行

时间:2013-09-24 21:19:40

标签: sql sql-server

我正在尝试从包含外键,日期和其他字段的源表中检索最新的行集。一组样本数据可以是:

create table #tmp (primaryId int, foreignKeyId int, startDate datetime, 
                                                    otherfield varchar(50))

insert into #tmp values (1, 1, '1 jan 2010', 'test 1')
insert into #tmp values (2, 1, '1 jan 2011', 'test 2')
insert into #tmp values (3, 2, '1 jan 2013', 'test 3')
insert into #tmp values (4, 2, '1 jan 2012', 'test 4')

我希望检索的数据形式是:

foreignKeyId maxStartDate            otherfield
------------ ----------------------- -------------------------------------------
1            2011-01-01 00:00:00.000 test 2
2            2013-01-01 00:00:00.000 test 3

也就是说,每foreignKeyId只显示一行显示最新的开始日期和相关的其他字段 - primaryId无关紧要。

我设法提出:

select t.foreignKeyId, t.startDate, t.otherField from #tmp t
    inner join (
                  select foreignKeyId, max(startDate) as maxStartDate
                      from #tmp
                      group by foreignKeyId
               ) s
           on t.foreignKeyId = s.foreignKeyId and s.maxStartDate = t.startDate 

但是(a)这使用内部查询,我怀疑这可能导致性能问题,(b)如果原始表中的两行具有相同的foreignKeyIdstartDate,它会提供重复的行

是否有一个查询只返回每个外键和开始日期的第一个匹配项?

2 个答案:

答案 0 :(得分:2)

根据您的sql server版本,请尝试以下操作:

select *
from (
    select *, rnum = ROW_NUMBER() over (
      partition by #tmp.foreignKeyId
      order by #tmp.startDate desc)
    from #tmp
) t
where t.rnum = 1

答案 1 :(得分:1)

如果你想修复你的尝试而不是重新设计它,那么

select t.foreignKeyId, t.startDate, t.otherField from #tmp t
inner join (
  select foreignKeyId, max(startDate) as maxStartDate, max(PrimaryId) as Latest
  from #tmp
  group by foreignKeyId
           ) s
on t.primaryId = s.latest
假设PrimaryID随着时间的推移而增加,那么

就完成了这项工作。

关于内部查询的问题也可以在假设某些索引的情况下休息。