如果我有一个简单的多对多用户和组连接表,例如:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(6) unsigned NOT NULL,
`name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `user_group` (
`user_id` int(6) unsigned NOT NULL,
`group_id` int(6) unsigned NOT NULL,
PRIMARY KEY (`user_id`, `group_id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `groups` (
`id` int(6) unsigned NOT NULL,
`name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `users` (`id`, `name`) VALUES
('1', 'Michael'),
('2', 'Sarah'),
('3', 'Steven'),
('4', 'Jane');
INSERT INTO `groups` (`id`, `name`) VALUES
('1', 'M Names'),
('2', 'S Names'),
('3', 'J Names'),
('4', 'Men'),
('5', 'Women');
INSERT INTO `user_group` (`user_id`, `group_id`) VALUES
('1', '1'),
('1', '4'),
('2', '2'),
('2', '5'),
('3', '2'),
('3', '4'),
('4', '3'),
('4', '5');
我试图弄清楚如何查看给定的一组用户是否构成现有组。
例如,如果我查询Michael,则返回组M Names
,因为该组完全由Michael组成。
如果我查询(Sarah,Steven),它会返回组'S Names'。
如果我查询(Sarah,Michael),则不会返回任何组。
可以轻松查询给定用户组所在的组:
SELECT * FROM `user_group`
WHERE `user_id` in ('2', '3');
但是我不知道如何将其限制为只有所有给定用户都是其成员的组。
答案 0 :(得分:2)
(更新,添加一些东西,使其不仅仅是一个子集,而是完全匹配)
我假设你想要所有用户都在一起的组。或者用户是子集的地方。以下查询将完成工作(除非我犯了错误)
SELECT g.Name
FROM groups g
INNER JOIN user_group ug on (ug.group_id=g.id)
WHERE ug.user_id IN (1,4)
GROUP BY g.id
HAVING COUNT(ug.user_id) = 2
解释:首先,您基本上(可能)希望按user_group
过滤user_id
以查找包含任何用户ID(WHERE
- 子句)的组,然后您想要选择具有所有用户ID(GROUP
和HAVING
- 子句)的组。
但是,此查询有两个不同的部分:where子句中的用户ID(在本例中为1,4
)和having子句中的user_ids计数(在本例中为2
)。
<强>更新强>
现在,由于您的帖子建议您想要完全匹配,因此您可以添加以下内容HAVING
-
AND COUNT(ug.user_id) = (SELECT COUNT(*) FROM user_group ug2 WHERE ug2.group_id=g.id)
确保该组的用户数与查询用户数相同。
答案 1 :(得分:2)
尝试此查询(适用于MySql 8):
WITH usr AS (
SELECT 'Sarah' usr_name
UNION
SELECT 'Steven'
),
usr_id AS (
SELECT * FROM usr
LEFT JOIN users u ON u.name = usr.usr_name
)
SELECT * FROM (
SELECT group_id
FROM user_group ug
LEFT JOIN usr_id u ON ug.user_id = u.id
GROUP BY group_id
HAVING count(*) = count(id)
AND count(*) = (SELECT count(*) FROM usr)
) qq
JOIN `groups` g ON g.id = qq.group_id
工作演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7621f99e0b2d0bf1ec6fbfdc55424c48
WITH usr AS ( SELECT 'Sarah' usr_name UNION SELECT 'Steven' ), usr_id AS ( SELECT * FROM usr LEFT JOIN users u ON u.name = usr.usr_name ) SELECT * FROM ( SELECT group_id FROM user_group ug LEFT JOIN usr_id u ON ug.user_id = u.id GROUP BY group_id HAVING count(*) = count(id) AND count(*) = (SELECT count(*) FROM usr) ) qq JOIN `groups` g ON g.id = qq.group_id
group_id | id | name -------: | -: | :------ 2 | 2 | S Names
WITH usr AS ( SELECT 'Michael' usr_name ), usr_id AS ( SELECT * FROM usr LEFT JOIN users u ON u.name = usr.usr_name ) SELECT * FROM ( SELECT group_id FROM user_group ug LEFT JOIN usr_id u ON ug.user_id = u.id GROUP BY group_id HAVING count(*) = count(id) AND count(*) = (SELECT count(*) FROM usr) ) qq JOIN `groups` g ON g.id = qq.group_id
group_id | id | name -------: | -: | :------ 1 | 1 | M Names
WITH usr AS ( SELECT 'Michael' usr_name UNION SELECT 'Sarah' ), usr_id AS ( SELECT * FROM usr LEFT JOIN users u ON u.name = usr.usr_name ) SELECT * FROM ( SELECT group_id FROM user_group ug LEFT JOIN usr_id u ON ug.user_id = u.id GROUP BY group_id HAVING count(*) = count(id) AND count(*) = (SELECT count(*) FROM usr) ) qq JOIN `groups` g ON g.id = qq.group_id
group_id | id | name -------: | -: | :---
db&lt;&gt;小提琴here