【问题标题】:Select latest row for each group from oracle从 oracle 中为每个组选择最新行
【发布时间】:2017-03-17 05:09:03
【问题描述】:

我在留言簿中有一张包含用户 cmets 的表格。列是:id、user_id、title、comment、timestamp。

我需要为每个用户选择最新的一行。 我尝试使用 group by 执行此操作,但没有管理它,因为我无法在我按 user_id 分组的同一查询中选择其他任何内容:

SELECT user_id, MAX(ts) FROM comments GROUP BY user_id

例如,在这个查询中,我不能添加到还选择列 id、tilte 和 comment。如何做到这一点?

【问题讨论】:

    标签: sql oracle greatest-n-per-group


    【解决方案1】:

    您可以使用JOIN 来构建您的查询:

    select c.*
    from comments c join
         (select user_id, max(ts) as maxts
          from comments c2
          group by user_id
         ) cc
         on c.user_id = cc.user_id and c.ts = cc.maxts;
    

    还有其他方法。典型的建议是使用row_number():

    select t.*
    from (select c.*, row_number() over (partition by user_id order by ts desc) as seqnum
          from comments c
         ) c
    where seqnum = 1;
    

    这两个查询略有不同。如果用户的最新评论具有完全相同的ts,则第一个将返回重复项。第二个返回每个用户一行。

    【讨论】:

      【解决方案2】:

      您可以使用分析函数

      SELECT *
        FROM (SELECT c.*,
                     rank() over (partition by user_id order by ts desc) rnk
                FROM comments c)
       WHERE rnk = 1
      

      根据您希望如何处理平局(如果可以有两行具有相同的user_idts),您可能需要使用row_numberdense_rank 函数而不是rank。如果有平局,rank 将允许多行排在第一位。 row_number 如果出现平局,将任意返回一行。 dense_rank 对于并列第一行的行为类似于 rank,但会认为下一行是第二行而不是第三行,假设两行并列第一。

      【讨论】:

        【解决方案3】:

        使用dense rank first/last函数有一个非常简单和非常有效的解决方案:

        select id,
               max(user_id) keep (dense_rank last order by ts) over (partition by id) as user_id,
               max(title)   keep (dense_rank last order by ts) over (partition by id) as title,
               max(comment) keep (dense_rank last order by ts) over (partition by id) as comment,
               max(ts)                                                                as ts
        from   comments;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-06
          • 2021-07-30
          • 2015-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多