我需要从 MySQL 表中选择对话 ID,其中对话中的用户与数组(如 (2, 5))中提供的用户完全匹配 - 应该返回 1 作为对话 ID。
数据库表的摘录如下:
user_ids (2, 5)
conversation_users:
conversation_id user_id
1 2
1 5
2 2
2 6
这可以在单个查询中完成吗?
编辑 - 2014 年 6 月 26 日
实际上,经过一些测试后,这并不总是能正常工作。如果属于某个对话的用户数量多于数组中的用户数量,它仍会返回这些用户所属的所有对话。
我希望获得数组中的用户与对话中的用户的精确匹配。
在下面的示例中,对话 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
最佳答案
是的,可以通过使用 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'
但是,这可能不是一个非常灵活的方法,因为它期望用户列表是一个排序的逗号分隔字符串。
工作 fiddle :http://sqlfiddle.com/#!2/4c82d/13
第三个选项:
使用子查询来仅获取只有 2 个用户的对话,而不是使用 GROUP_CONCAT
(如上面的第二个选项)。然后将此子查询与主表连接,并应用上面给出的第一个选项中使用的相同过滤器(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
应该是一个更好的方法,因为它不依赖于第二个选项所需的排序的逗号分隔列表。
工作 fiddle :http://sqlfiddle.com/#!2/4c82d/21
关于MySQL查询从多行获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24388429/