特定のユーザーがメッセージを交換したすべてのユーザーのリストを、最後に送信されたメッセージのタイムスタンプと最後に受信されたメッセージのタイムスタンプと共に取得する必要があります。これを単一のクエリで実行したいと考えています。
結果は次のようになります。
[
[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 がこれを最適化するかどうか、また同じクエリを実行するより良い方法を知りたいです。
ありがとう。マルク