Select 来自 oracle 的每个组的最新行

Select latest row for each group from oracle

我有一个 table 留言簿中有用户评论。列为:id、user_id、标题、评论、时间戳。

我需要 select 每个用户的最新行。 我曾尝试使用 group by 来执行此操作,但还没有成功,因为我不能 select 在我按 user_id:

分组的同一查询中的任何其他内容
SELECT user_id, MAX(ts) FROM comments GROUP BY user_id

例如,在此查询中,我也无法添加到 select 列 id、tilte 和 comment。如何做到这一点?

您可以使用 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,则第一个将 return 重复。第二个 return 每个用户一行。

您可以使用解析函数

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 函数而不是 rankrank 如果有平局,将允许多行排在第一位。如果出现平局,row_number 会任意 return 一行。 dense_rank 对于并列第一的行的行为类似于 rank,但会认为下一行是第二行而不是第三行,假设两行并列第一。

这类问题有一个非常简单有效的解决方案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;