1

我有一个像这样的设置:

conversations(id) 

notifications(id, conversation_id, user_id)

users(id)

如果对话涉及某人,则user将链接到conversationthrough notification

目标:我正在寻找专门针对给定 ID的conversations问题。 users


显而易见的:

SELECT DISTINCT conversations.* 
FROM "conversations" 
INNER JOIN "notifications" ON "notifications"."conversation_id" = "conversations"."id"
WHERE notifications.user_id IN (1, 2)

不起作用,因为它还会检索有关以下内容的对话:

  • id 为 1、2 和 3 的用户
  • id 为 1 和 4 的用户
  • id 为 2 和 4 的用户

这是不希望的。

4

2 回答 2

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 relationship

特殊要求是排除其他匹配项。我NOT EXISTS用于此目的。您也可以使用LEFT JOIN / IS NULLNOT IN。更多详细信息:
选择其他表中不存在的行

同一用户可能有多个通知

为避免结果中的重复对话,您可以使用DISTINCTGROUP 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}')
  )
于 2013-11-19T23:45:46.853 回答
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 的答案就是你所需要的。

于 2013-11-19T23:46:01.070 回答