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_id
和 ts
),您可能希望使用 row_number
或 dense_rank
函数而不是 rank
。 rank
如果有平局,将允许多行排在第一位。如果出现平局,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;
我有一个 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_id
和 ts
),您可能希望使用 row_number
或 dense_rank
函数而不是 rank
。 rank
如果有平局,将允许多行排在第一位。如果出现平局,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;