我需要检索特定用户已交换的所有用户的列表 消息,以及发送的最后一条消息的时间戳和 收到的最后一条消息的时间戳。我想在一个查询中执行此操作。
结果将是这样的:
[
[0] {
:uname => "fred",
:last_received => 2013-04-09 22:47:20 UTC,
:last_sent => 2013-04-09 22:47:28 UTC
},
[1] {
:uname => "barney",
:last_received => nil,
:last_sent => 2013-06-16 16:25:56 UTC
},
[2] {
:uname => "dino",
:last_received => 2013-06-09 17:52:54 UTC,
:last_sent => 2013-06-10 15:56:52 UTC
}
]
简化的架构是:
CREATE TABLE users (
id serial NOT NULL,
uname text NOT NULL,
created_at timestamp without time zone DEFAULT timezone('utc'::text, now())
)
CREATE TABLE messages (
id serial NOT NULL,
sender_id integer NOT NULL,
recipient_id integer NOT NULL,
message_text_id integer,
created_at timestamp without time zone DEFAULT timezone('utc'::text, now())
)
我有一个查询来执行此操作,但由于它确实在用户上留下了联接,我就是这样 担心随着用户数量的增加它会变慢 - 我 不知道postgresql是否会优化它以避免这种情况发生。
WITH t AS (
select sender_id, recipient_id, max(created_at) as latest_date
from messages
where sender_id = #{id} or recipient_id = #{id}
group by sender_id, recipient_id
)
select uname, t1.latest_date last_received, t2.latest_date last_sent
from users
left join t t1 on t1.sender_id = users.id and t1.sender_id != #{id}
left join t t2 on t2.recipient_id = users.id and t2.recipient_id != #{id}
where t1.latest_date is not null or t2.latest_date is not null
我有兴趣了解postgresql是否会对此进行优化,以及查看执行相同查询的更好方法。
感谢。 马克
答案 0 :(得分:2)
你可以尝试以下几行 - 尝试使用explain
来查看哪个看起来最好。
SELECT u.uname, max(x.last_received) last_received, max(x.last_sent) last_sent
FROM (
SELECT sender_id user_id, max(created_at) last_received, null last_sent
FROM messages
WHERE recipient_id = #{id}
GROUP BY recipient_id
UNION ALL
SELECT recipient_id user_id, null last_received, max(created_at) last_sent
FROM messages
WHERE sender_id = #{id}
GROUP BY sender_id
) x
JOIN users u
ON x.user_id = u.user_id