【问题标题】:SQL Server : group by with corresponding row valuesSQL Server:按相应的行值分组
【发布时间】:2016-01-11 05:03:42
【问题描述】:

我需要为具有多个日期和序列列的表编写一个 T-SQL 组查询:

DROP TABLE #temp
CREATE TABLE #temp(
       id char(1),
       dt DateTime,
       seq int)

Insert into #temp values('A','2015-03-31 10:00:00',1)
Insert into #temp values('A','2015-08-31 10:00:00',2)
Insert into #temp values('A','2015-03-31 10:00:00',5)
Insert into #temp values('B','2015-09-01 10:00:00',1)
Insert into #temp values('B','2015-09-01 10:00:00',2)

我希望结果仅包含项目 A、B 及其 最新日期对应 seq 编号,例如:

id  MaxDate CorrespondentSeq
A   2015-08-31 10:00:00.000 2
B   2015-09-01 10:00:00.000 2

我正在尝试(显然错了!):

select id, max(dt) as MaxDate, max(seq) as CorrespondentSeq
from #temp
group by id

返回:

id  MaxDate CorrespondentSeq
A   2015-08-31 10:00:00.000 5  <-- 5 is wrong
B   2015-09-01 10:00:00.000 2

我怎样才能做到这一点?

编辑

dt datetime 列有重复值(完全相同的日期!)

我使用的是 SQL Server 2005

【问题讨论】:

  • 如果有相同 id 的日期重复的行,那么您需要指定查询处理器应该使用什么来确定要返回哪些重复。

标签: tsql sql-server-2005


【解决方案1】:

您可以使用排名子选择来仅获取 id 排名最高的条目:

select id, dt, seq 
from (
        select id, dt, seq, rank() over (partition by id order by dt desc, seq desc) as r
        from #temp            
     ) ranked
where r=1;

【讨论】:

  • 我非常喜欢这个解决方案,因为我认为它最能解释...首先它按 dt 对表排序,按 id 对其进行分区...然后选择带有rank 1 的行。 ..聪明!
【解决方案2】:
SELECT ID, DT, SEQ 
FROM (
        SELECT ID, DT, SEQ, Row_Number()
            OVER (PARTITION BY id ORDER BY dt DESC, seq DESC) AS row_number
        FROM temp            
     ) cte
WHERE row_number = 1;

演示:http://www.sqlfiddle.com/#!3/3e3d5/5

【讨论】:

    【解决方案3】:

    经过反复试验,也许我找到了解决方案,但我不完全确定这是正确的:

    select A.id, B.dt, max(B.seq) 
    from (select id, max(dt) as maxDt
          from #temp
          group by id) as A
    inner join #temp as B on A.id = B.id AND A.maxDt = B.dt
    group by A.id, B.dt
    

    【讨论】:

      【解决方案4】:
      Select id, dt, seq
      From #temp t
      where dt = (Select Max(dt) from #temp
                  Where id = t.Id)
      

      如果存在重复行,那么您还需要指定查询处理器应该使用什么来确定要返回哪些重复行。假设您想要seq 的最小值,

      那么你可以写:

      Select id, dt, seq
      From #temp t
      where dt = (Select Max(dt) from #temp
                  Where id = t.Id)
         and seq = (Select Min(Seq) from #temp
                    where id = t.Id
                       and dt = t.dt)
      

      【讨论】:

      • 如果等于日期,则返回:id dt seq B 2015-09-01 10:00:00.000 1 B 2015-09-01 10:00:00.000 2 A 2015-08-31 10:00:00.000 2(同时返回 B 行!)
      猜你喜欢
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 2011-06-20
      • 2018-04-09
      • 2013-09-13
      • 1970-01-01
      • 2017-01-27
      相关资源
      最近更新 更多