Select latest row for each group from oracle

六月ゝ 毕业季﹏ 提交于 2019-11-30 07:10:50

问题


I have a table with user comments in a guestbook. Columns are: id, user_id, title, comment, timestamp.

I need to select the latest row for each user. I have tried to do this with group by but havent managed it because i cant select anything else in the same query where i group by user_id:

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

for example in this query i cant add to also select columns id, tilte and comment. How can this be done?


回答1:


You can use analytic functions

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

Depending on how you want to handle ties (if there can be two rows with the same user_id and ts), you may want to use the row_number or dense_rank function rather than rank. rank would allow multiple rows to be first if there was a tie. row_number would arbitrarily return one row if there was a tie. dense_rank would behave like rank for the rows that tied for first but would consider the next row to be second rather than third assuming two rows tie for first.




回答2:


You can build on your query using a 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;

There are other ways. Typical advice is to use 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;

These two queries are subtly different. The first will return duplicates if the most recent comment for a user had exactly the same ts. The second returns one row per user.




回答3:


This type of problems has a very simple and very efficient solution with the dense rank first/last function:

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;


来源:https://stackoverflow.com/questions/40404497/select-latest-row-for-each-group-from-oracle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!