これがデータベース構造であるとしましょう:
SELECT * FROM `pms` where id_to = 1 or id_from = 1
これは、彼が受信または送信したすべてのメッセージを返します。
では、ユーザー 1 の各会話から最後のメッセージを取得するにはどうすればよいでしょうか?
PD: 2 人のユーザー間で 1 つ以上のメッセージがある場合、それを会話と呼びます
-編集-
したがって、このデータベースの内容を考えると:
ID 4 と 6 を取得したい
id
これは、自動インクリメント列であると想定しています。
SELECT MAX(id) AS id
FROM pms
WHERE id_to = 1 OR id_from = 1
GROUP BY (IF(id_to = 1, id_from, id_to))
id_from
インデックスが作成されていると仮定するとid_to
、MySQL は OR の処理方法がわからないため、このバリエーションのパフォーマンスが向上する可能性が高くなります。
SELECT MAX(id) AS id FROM
(SELECT id, id_from AS id_with
FROM pms
WHERE id_to = 1
UNION ALL
SELECT id, id_to AS id_with
FROM pms
WHERE id_from = 1) t
GROUP BY id_with
これらの ID のメッセージを取得する方法は次のとおりです。
SELECT * FROM pms WHERE id IN
(SELECT MAX(id) AS id FROM
(SELECT id, id_from AS id_with
FROM pms
WHERE id_to = 1
UNION ALL
SELECT id, id_to AS id_with
FROM pms
WHERE id_from = 1) t
GROUP BY id_with)
select pms.* from pms
inner join
(select max(fecha) as max_fecha,
if(id_to<id_from,id_to,id_from) min_id,
if(id_to<id_from,id_from,id_to) max_id
from pms where id_to = 1 or id_from = 1
group by if(id_to<id_from,id_to,id_from),if(id_to<id_from,id_from,id_to)) t
on (if(pms.id_to<pms.id_from,pms.id_to,pms.id_from)=t.min_id)
and (if(pms.id_to<pms.id_from,pms.id_from,pms.id_to)=t.max_id)
and (pms.fecha=t.max_fecha)
また、テーブルの id_to と id_from が、ステートメント (id_to+id_from) でのオーバーフローを防ぐのに十分小さい場合、単純なクエリは次のとおりです。
select pms.* from pms
inner join
(select max(fecha) as max_fecha, id_to+id_from as sum_id
from pms where id_to = 1 or id_from = 1
group by id_to+id_from) t
on ((pms.id_to+pms.id_from)=t.sum_id)
and (pms.fecha=t.max_fecha)
where pms.id_to = 1 or pms.id_from = 1
このクエリは機能するはずです:
SELECT a.*
FROM pms a
INNER JOIN (
SELECT id_to, id_from, MAX(fecha) AS fecha
FROM pms
WHERE (id_to = 1 OR id_from = 1)
GROUP BY LEAST(id_to, id_from)
) b
ON a.fecha = b.fecha AND
(a.id_to = b.id_to OR
a.id_from = b.id_from);
id
asがあり、メッセージを時系列でログに記録している場合PRIMARY KEY
は、次のようにさらに最適化および簡略化できます。
SELECT a.*
FROM pms a
INNER JOIN (
SELECT MAX(id) AS id
FROM pms
WHERE (id_to = 1 OR id_from = 1)
GROUP BY LEAST(id_to, id_from)
) b
ON a.id = b.id;