Ini adalah kasus pembagian relasional . Kami telah mengumpulkan gudang teknik di bawah pertanyaan terkait ini:
Kesulitan khusus adalah untuk mengecualikan pengguna tambahan. Pada dasarnya ada 4 teknik.
Saya sarankan LEFT JOIN
/ IS NULL
:
SELECT cu1.conversation_id
FROM conversation_user cu1
JOIN conversation_user cu2 USING (conversation_id)
LEFT JOIN conversation_user cu3 ON cu3.conversation_id = cu1.conversation_id
AND cu3.user_id NOT IN (3,32)
WHERE cu1.user_id = 32
AND cu2.user_id = 3
AND cu3.conversation_id IS NULL;
Atau NOT EXISTS
:
SELECT cu1.conversation_id
FROM conversation_user cu1
JOIN conversation_user cu2 USING (conversation_id)
WHERE cu1.user_id = 32
AND cu2.user_id = 3
AND NOT EXISTS (
SELECT 1
FROM conversation_user cu3
WHERE cu3.conversation_id = cu1.conversation_id
AND cu3.user_id NOT IN (3,32)
);
Kedua kueri tidak bergantung pada UNIQUE
batasan untuk (conversation_id, user_id)
, yang mungkin atau mungkin tidak pada tempatnya. Artinya, kueri bahkan berfungsi jika user_id
32 (atau 3) dicantumkan lebih dari satu kali untuk percakapan yang sama. Anda akan dapatkan baris duplikat dalam hasil, dan perlu menerapkan DISTINCT
atau GROUP BY
.
Satu-satunya syarat adalah yang Anda rumuskan:
Kueri yang diaudit
kueri yang Anda tautkan di komentar tidak akan berhasil. Anda lupa mengecualikan peserta lain. Seharusnya seperti:
SELECT * -- or whatever you want to return
FROM conversation_user cu1
WHERE cu1.user_id = 32
AND EXISTS (
SELECT 1
FROM conversation_user cu2
WHERE cu2.conversation_id = cu1.conversation_id
AND cu2.user_id = 3
)
AND NOT EXISTS (
SELECT 1
FROM conversation_user cu3
WHERE cu3.conversation_id = cu1.conversation_id
AND cu3.user_id NOT IN (3,32)
);
Yang mirip dengan dua kueri lainnya, kecuali bahwa itu tidak akan mengembalikan beberapa baris jika user_id = 3
ditautkan beberapa kali.