我需要从MySQL表中选择一个conversation_id,其中对话中的用户与数组中提供的用户完全匹配,例如(2,5) - 应该返回1作为会话ID。
db表的提取如下:
user_ids (2, 5)
conversation_users:
conversation_id user_id
1 2
1 5
2 2
2 6
这可以在一个查询中完成吗?
编辑 - 26.06.2014
实际上,在做了一些测试后,这并不总能正常工作。如果属于对话的用户数多于数组中的用户数,则仍会返回这些用户所属的所有对话。
我希望将数组中的用户与对话中的用户完全匹配。
在下面的示例中,会话6和7都返回,但不应返回任何行:
SELECT `conversation_id` FROM `conversation_user` WHERE `user_id` IN (70, 426)
GROUP BY `conversation_id` HAVING COUNT(DISTINCT `user_id`) = 2;
conversation_user_id conversation_id user_id
14 6 70
15 6 29
16 6 442
17 6 425
18 6 426
19 7 70
20 7 442
21 7 426
22 7 499
23 7 425
24 7 29
答案 0 :(得分:2)
是的,可以使用WHERE
,GROUP BY
和HAVING
条款的组合来实现这一点:
SELECT conversation_id
FROM conversation_users
WHERE user_id IN (2,5)
GROUP BY conversation_id
HAVING COUNT(DISTINCT user_id) = 2
第二个选项:
如果一个对话中有两个以上的记录(用户),那么您有几个选择。下面给出了一个选项,其中删除了WHERE
子句并使用了GROUP_CONCAT
,如下所示:
SELECT `conversation_id` FROM `conversation_user`
GROUP BY `conversation_id`
HAVING COUNT(DISTINCT `user_id`) = 2
AND GROUP_CONCAT(DISTINCT `user_id` ORDER BY `user_id` ASC SEPARATOR ',') = '70,426'
但是,这可能不是一种非常灵活的方法,因为它希望用户列表是一个以逗号分隔的有序字符串。
工作小提琴:http://sqlfiddle.com/#!2/4c82d/13
第三个选项:
使用子查询来获取仅包含2个用户的对话,而不是GROUP_CONCAT
(如上面第2个选项中所述)。然后将此子查询与主表连接,并应用与上面给出的第一个选项中使用的相同的过滤器(WHERE
和GROUP BY
),如下所示:
SELECT `conversation_id`
FROM `conversation_user`
JOIN (
SELECT `conversation_id` t_cid FROM `conversation_user`
GROUP BY `conversation_id`
HAVING COUNT(DISTINCT `user_id`) = 2
) t
ON t.t_cid = `conversation_user`.`conversation_id`
WHERE `user_id` IN (70, 426)
GROUP BY `conversation_id`
HAVING COUNT(DISTINCT `user_id`) = 2
应该是更好的方法,因为它不依赖于第二个选项中所需的已排序的逗号分隔列表。