微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mysql – SQL:在双重多对多关系中查找交集

以下是我的架构和数据的简化版本:

用户

id | name
 1 | Peter
 2 | Max
 3 | Susan

餐馆:

id | name
 1 | Mario
 2 | Ali
 3 | Alfonzo
 4 | BurgerQueen

菜肴:

id | name
 1 | Burger
 2 | Pizza
 3 | Salad

users_dishes:

user_id | dish_id
      1 | 1
      2 | 1
      2 | 2
      3 | 2
      3 | 3

restaurants_dishes:

restaurant_id | dish_id
            1 | 2
            1 | 3
            2 | 1
            2 | 3
            3 | 1
            3 | 2
            3 | 3
            4 | 1

所以我有三个实体:用户,餐馆和菜肴.
和两个多对多的关系.

>用户菜肴的关系定义了用户可以吃的东西.
>关系餐厅菜肴定义了餐厅可以提供的服务.

作为输入,我有一个用户ID列表.
我现在需要的是找到所有餐馆,列表中的所有用户都可以吃他们喜欢的东西.

请考虑以下查询

select u.name as user, group_concat(distinct r.name) as dishes
from users u
join users_dishes ud on ud.user_id = u.id
join restaurants_dishes rd on rd.dish_id = ud.dish_id
join restaurants r on r.id = rd.restaurant_id
group by u.id

显示了每个用户都可以访问的所有餐馆.

user  | restaurants
Peter | Alfonzo,Ali,BurgerQueen
Max   | Alfonzo,Ali,BurgerQueen,Mario
Susan | Alfonzo,Ali,Mario

所以我需要的是集合的交集.
你已经可以看到所有三个用户都可以去Alfonzo和Ali.
但彼得不能去马毛.苏珊不能去BurgerQueen.

结果(对于用户ID 1,2,3)应该是:

id | name
 2 | Ali
 3 | Alfonzo

对于ID 1,2,它应该是

id | restaurant
 2 | Ali
 3 | Alfonzo
 4 | BurgerQueen

对于ID 2,3,它应该是

id | restaurant
 1 | Mario
 2 | Ali
 3 | Alfonzo

您可以使用以下sql脚本创建架构和示例数据:

CREATE TABLE users (id INT AUTO_INCREMENT,name varchar(100),PRIMARY KEY (id));
INSERT INTO users(name) VALUES ('Peter'),('Max'),('Susan');
CREATE TABLE restaurants (id INT AUTO_INCREMENT,name varchar(100),PRIMARY KEY (id));
INSERT INTO restaurants(name) VALUES ('Mario'),('Ali'),('Alfonzo'),('BurgerQueen');
CREATE TABLE dishes (id INT AUTO_INCREMENT,name varchar(100),PRIMARY KEY (id));
INSERT INTO dishes(name) VALUES ('Burger'),('Pizza'),('Salad');
CREATE TABLE users_dishes (user_id INT,dish_id INT,PRIMARY KEY (user_id, dish_id),INDEX (dish_id, user_id));
INSERT INTO users_dishes(user_id, dish_id) VALUES (1,1),(2,1),(2,2),(3,2),(3,3);
CREATE TABLE restaurants_dishes (restaurant_id INT,dish_id INT,PRIMARY KEY (restaurant_id, dish_id),INDEX (dish_id, restaurant_id));
INSERT INTO restaurants_dishes(restaurant_id, dish_id) VALUES (1,2),(1,3),(2,1),(2,3),(3,1),(3,2),(3,3),(4,1);

我还准备了SQL-fiddle on db-fiddle.com.

我还要提一下,我需要一个兼容MysqL 5.7和MariaDB 10.1的解决方

解决方法:

我将您的查询修改为按餐馆名称分组,并计算每个人可以吃的用户,并添加条件:

select r.id, r.name as restaurant
from users u
join users_dishes ud on ud.user_id = u.id
join restaurants_dishes rd on rd.dish_id = ud.dish_id
join restaurants r on r.id = rd.restaurant_id
group by r.id, r.name
having count(distinct u.id) = (select count(*) from users);

结果:

| id  | restaurant |
| --- | ---------- |
| 2   | Ali        |
| 3   | Alfonzo    |

见@L_404_1@
您可以添加条件来检查用户列表,如下所示:

select r.id, r.name as restaurant
from users u
join users_dishes ud on ud.user_id = u.id
join restaurants_dishes rd on rd.dish_id = ud.dish_id
join restaurants r on r.id = rd.restaurant_id
where u.id in (1, 2, 3)
group by r.id, r.name
having count(distinct u.id) = 3;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐