根据相关聚合列,选择组中的非聚合列

时间:2016-09-12 08:58:26

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

我试图从数据库中获取对话列表,并且我希望最近显示的消息与它们一起显示。我无法找到允许我这样做的查询(而且不是N + 1)。

我有这些表格:

chats(id, user_id, post_id, created_at)
messages(id, user_id, chat_id, body, created_at)

我有一个这样的疑问:

select chats.id, chats.user_id, m.latest from chats
inner join (
    select chat_id, max(created_at) as latest from messages
    group by chat_id
) as m on m.chat_id = chats.id; 

但是我想从与max(created_at)结果对应的行中添加消息正文。是否有可能获得这样的相关专栏?

2 个答案:

答案 0 :(得分:3)

使用标准SQL,可以使用窗口函数完成(参见sagi的答案)。

使用Postgres,专有distinct on()通常比使用窗口函数的等效解决方案更快:

select chats.id, chats.user_id, m.body, m.latest 
from chats
  join (
    select distinct on (chat_id) chat_id, body, created_at as latest 
    from messages
    order by chat_id, created_at desc;
  ) as m on m.chat_id = chats.id; 

使用窗口函数的解决方案更灵活。您也可以使用该消息获取最新的两条(或三条或者......)消息,而distinct on()只能获得一条消息。

答案 1 :(得分:2)

尝试使用ROW_NUMBER()

select chats.id, chats.user_id, m.body from chats
inner join (
    select chat_id,body ,
           row_number() OVER(PARTITION BY chat_id ORDER BY created_at DESC) as rnk
    from messages
) m on m.chat_id = chats.id and m.rnk = 1;