たとえば、2人のユーザーがダイレクトメッセージで話しているとすると、メッセージの会話ができます。その会話から最新のメッセージを選択し、メッセージの受信トレイに会話リンクとして表示したいとします。FacebookとTwitterの方法です。メッセージは機能します。次に、最後に送信されたメッセージをクリックして、会話全体を表示できます。
ユーザー間で送信されるすべてのメッセージを含む私のメッセージテーブルは、次の形式です。
sourceUserIdはメッセージを送信したユーザーのID、targetUserIdはメッセージを受信したユーザーのID、bodyはメッセージ、timeはメッセージが送信されたときのタイムスタンプです。私はbodyをabcとして保持しています...そしてこの例を単純にするために時間1234、それらはすべて異なる値です。
+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId | body | time |
+----+--------------+--------------+--------+------+
| 1 | 1 | 2 | abc... | 1234 |
| 2 | 3 | 1 | abc... | 1234 |
| 3 | 3 | 1 | abc... | 1234 |
| 4 | 1 | 3 | abc... | 1234 |
| 5 | 2 | 1 | abc... | 1234 |
| 6 | 1 | 2 | abc... | 1234 |
| 7 | 3 | 1 | abc... | 1234 |
| 8 | 4 | 1 | abc... | 1234 |
| 9 | 5 | 4 | abc... | 1234 |
| 10 | 3 | 2 | abc... | 1234 |
+----+--------------+--------------+--------+------+
1人のユーザーのすべてのメッセージ(送信および受信)を取得するには、次のクエリを使用します。
SELECT sourceUserId, targetUserId, body, UNIX_TIMESTAMP(time)
FROM `usermessages`
WHERE targetUserId = 1
OR sourceUserId = 1
ORDER BY id DESC
LIMIT 10
+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId | body | time |
+----+--------------+--------------+--------+------+
| 1 | 1 | 2 | abc... | 1234 |
| 2 | 3 | 1 | abc... | 1234 |
| 3 | 3 | 1 | abc... | 1234 |
| 4 | 1 | 3 | abc... | 1234 |
| 5 | 2 | 1 | abc... | 1234 |
| 6 | 1 | 2 | abc... | 1234 |
| 7 | 3 | 1 | abc... | 1234 |
| 8 | 4 | 1 | abc... | 1234 |
+----+--------------+--------------+--------+------+
ただし、2人のユーザー間の会話からの最新のメッセージだけでなく、同じメッセージ会話の複数のインスタンスを返します。たとえば、行2、3、および4はすべてまったく同じ会話を示します。
次のクエリを使用して、targetUserId(ユーザーが受信したメッセージ)に対してのみクエリを機能させることができます。
SELECT sourceUserId, targetUserId, body, UNIX_TIMESTAMP(time)
FROM `usermessages`
WHERE targetUserId = 1
GROUP BY sourceUserId
ORDER BY id DESC
LIMIT 10
+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId | body | time |
+----+--------------+--------------+--------+------+
| 2 | 3 | 1 | abc... | 1234 |
| 5 | 2 | 1 | abc... | 1234 |
| 8 | 4 | 1 | abc... | 1234 |
+----+--------------+--------------+--------+------+
これとは逆に(ユーザーから送信されたメッセージ)、WHEREとGROUPBYが交換されたばかりであることに注意してください。
SELECT sourceUserId, targetUserId, body, UNIX_TIMESTAMP(time)
FROM `usermessages`
WHERE sourceUserId = 1
GROUP BY targetUserId
ORDER BY id DESC
LIMIT 10
+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId | body | time |
+----+--------------+--------------+--------+------+
| 1 | 1 | 2 | abc... | 1234 |
| 4 | 1 | 3 | abc... | 1234 |
+----+--------------+--------------+--------+------+
しかし、2つの結果を組み合わせると、group by targetUserId, sourceUserId
1から(2,3,4)までのすべての送信メッセージがグループ化されるため、正しい結果が得られません。
返却したいもの
このようなクエリの擬似コードは次のようになると思います。
SELECT sourceUserId, targetUserId, body, UNIX_TIMESTAMP(time)
FROM `usermessages`
WHERE sourceUserId = 1
OR targetUserId = 1
GROUP BY (If targetUserId != 1), (If sourceUserId != 1)
ORDER BY id DESC
LIMIT 10
+----+--------------+--------------+--------+------+
| id | sourceUserId | targetUserId | body | time |
+----+--------------+--------------+--------+------+
| 1 | 1 | 2 | abc... | 1234 |
| 2 | 3 | 1 | abc... | 1234 |
| 8 | 4 | 1 | abc... | 1234 |
+----+--------------+--------------+--------+------+