我的设置如下:
conversations(id)
notifications(id, conversation_id, user_id)
users(id)
如果对话涉及某人,则user
会与conversation
至notification
相关联。
目标:我正在寻找conversations
关于给定ID的完全 users
。{/ p>
显而易见:
SELECT DISTINCT conversations.*
FROM "conversations"
INNER JOIN "notifications" ON "notifications"."conversation_id" = "conversations"."id"
WHERE notifications.user_id IN (1, 2)
不起作用,因为它还会检索有关以下内容的对话:
这是不可取的。
答案 0 :(得分:1)
这假设每个用户只能一次加入对话:
SELECT c.*
FROM conversations c
JOIN notifications n1 ON n1.conversation_id = c.id
JOIN notifications n2 ON n2.conversation_id = c.id
WHERE n1.user_id = 1
AND n2.user_id = 2
AND NOT EXISTS (
SELECT 1
FROM notifications n3
WHERE n3.conversation_id = c.id
AND n3.user_id <> ALL ('{1,2}')
)
这是关系师的一个特例。在这个相关的问题下,我们已经汇集了一整套技术: How to filter SQL results in a has-many-through relation
特殊要求是排除其他匹配。为此,我使用NOT EXISTS
。您还可以使用LEFT JOIN / IS NULL
或NOT IN
。更多细节:
Select rows which are not present in other table
为避免结果中出现重复的对话,除上述内容外,您还可以使用DISTINCT
或GROUP BY
。或者你开始抑制重复(可能更快):
SELECT c.*
FROM conversations c
WHERE EXISTS (
SELECT 1
FROM notifications n1
JOIN notifications n2 USING (conversation_id)
WHERE n1.conversation_id = c.id
AND n1.user_id = 1
AND n2.user_id = 2
)
AND NOT EXISTS (
SELECT 1
FROM notifications n3
WHERE n3.conversation_id = c.id
AND n3.user_id <> ALL ('{1,2}')
)
答案 1 :(得分:1)
SELECT DISTINCT conversations.*
FROM conversations c
JOIN notifications n1 ON n1.conversation_id = c.id
JOIN notifications n2 ON n2.conversation_id = n1.conversation_id AND n1.id <> n2.id
WHERE n1.user_id = 1 AND n2.User_Id =2
我认为问题要求User_Id = 1和User_Id = 2之间的对话...... 如果除了1和2之外的任何人都不应该参与对话,那么Eric的回答就是你所需要的。