从 oracle 中为每个组选择最新行
Posted
技术标签:
【中文标题】从 oracle 中为每个组选择最新行【英文标题】:Select latest row for each group from 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。如何做到这一点?
【问题讨论】:
【参考方案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_id
和ts
),您可能需要使用row_number
或dense_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;
【讨论】:
以上是关于从 oracle 中为每个组选择最新行的主要内容,如果未能解决你的问题,请参考以下文章
从Oracle SQL中的每个组中选择具有最大值的行[重复]
使用 Spark Scala 为数据中的每个组选择窗口操作后的最新时间戳记录