Select 分组依据中的非聚合列,基于相关聚合列
Select non-aggregate column in a group by, based on a related aggregate column
我正在尝试从数据库中获取对话列表,并且我希望与它们一起显示最新消息。我无法找到允许我执行此操作的查询(而且不是 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)
结果对应的行中添加消息正文。有没有可能得到这样的相关专栏?
尝试使用 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;
使用标准 SQL 这可以使用 window 函数来完成(参见 sagi 的回答)。
对于 Postgres,专有的 distinct on()
通常比使用 window 函数的等效解决方案更快:
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;
不过,使用 window 函数的解决方案更加灵活。您还可以获得最新的两条(或三条或...)消息,而 distinct on()
只会让您收到一条消息。
我正在尝试从数据库中获取对话列表,并且我希望与它们一起显示最新消息。我无法找到允许我执行此操作的查询(而且不是 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)
结果对应的行中添加消息正文。有没有可能得到这样的相关专栏?
尝试使用 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;
使用标准 SQL 这可以使用 window 函数来完成(参见 sagi 的回答)。
对于 Postgres,专有的 distinct on()
通常比使用 window 函数的等效解决方案更快:
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;
不过,使用 window 函数的解决方案更加灵活。您还可以获得最新的两条(或三条或...)消息,而 distinct on()
只会让您收到一条消息。