SQL:选择其不同值是另一个表的子集的行';不同的价值观
鉴于下表:SQL:选择其不同值是另一个表的子集的行';不同的价值观,sql,postgresql,Sql,Postgresql,鉴于下表: plan_role id | plan_id | role_id ----+---------+--------- 7 | 1 | 10 8 | 1 | 20 9 | 1 | 30 10 | 2 | 10 11 | 2 | 20 12 | 3 | 30 13 | 4 | 40 user_role id
plan_role
id | plan_id | role_id
----+---------+---------
7 | 1 | 10
8 | 1 | 20
9 | 1 | 30
10 | 2 | 10
11 | 2 | 20
12 | 3 | 30
13 | 4 | 40
user_role
id | user_id | role_id
----+---------+---------
8 | 100 | 10
9 | 100 | 20
10 | 100 | 40
11 | 200 | 10
12 | 200 | 20
13 | 200 | 30
14 | 200 | 40
将返回所有计划id的SQL查询是什么,使得给定用户id的角色id集是计划id的角色id集的超集
换句话说,如何为给定用户找到计划,以便该用户与每个计划至少共享所有角色
例如,user\u id
100应该返回plan\u id
s2,4,而user\u id
200应该返回1,2,3,4
为方便起见,以下是我使用的设置:
CREATE TABLE plan_role(
id serial PRIMARY KEY,
plan_id integer NOT NULL,
role_id integer NOT NULL
);
CREATE TABLE user_role(
id serial PRIMARY KEY,
user_id integer NOT NULL,
role_id integer NOT NULL
);
INSERT INTO plan_role (plan_id, role_id) VALUES (1, 10);
INSERT INTO plan_role (plan_id, role_id) VALUES (1, 20);
INSERT INTO plan_role (plan_id, role_id) VALUES (1, 30);
INSERT INTO plan_role (plan_id, role_id) VALUES (2, 10);
INSERT INTO plan_role (plan_id, role_id) VALUES (2, 20);
INSERT INTO plan_role (plan_id, role_id) VALUES (3, 30);
INSERT INTO plan_role (plan_id, role_id) VALUES (4, 40);
INSERT INTO user_role (user_id, role_id) VALUES (100, 10);
INSERT INTO user_role (user_id, role_id) VALUES (100, 20);
INSERT INTO user_role (user_id, role_id) VALUES (100, 40);
INSERT INTO user_role (user_id, role_id) VALUES (200, 10);
INSERT INTO user_role (user_id, role_id) VALUES (200, 20);
INSERT INTO user_role (user_id, role_id) VALUES (200, 30);
INSERT INTO user_role (user_id, role_id) VALUES (200, 40);
这种类型的查询听起来像
存在
或在
中:
select distinct pr.plan_id
from plan_role pr
where pr.role_id in (select ur.role_id
from user_role ur
where ur.user_id = 200
);
这将返回所有具有与用户200共享的角色的计划。我只需在此处使用
左连接和计划汇总来检查每个角色是否属于某个用户
SELECT t1.plan_id
FROM rms.plan_role t1
LEFT JOIN rms.user_role t2
ON t1.role_id = t2.role_id AND
t2.user_id = 100
GROUP BY t1.plan_id
HAVING SUM(CASE WHEN t2.id IS NULL THEN 1 ELSE 0 END) = 0
此处演示:
(MySQL中显示的演示,尽管Postgres中的语法几乎相同,但表名除外)这是通过查找缺少角色的用户,然后使用该集合来给出最终结果
select user_plans.* from
(
-- all users with all plans
select distinct user_id, plan_id from user_role, plan_role
) user_plans
left join
(
select user_plans_roles.plan_id, user_plans_roles.user_id from (
-- get the result assuming user has all plans and roles
select distinct plan_id, user_id, plan_role.role_id
from plan_role, user_role
) user_plans_roles
left join user_role users
on user_plans_roles.user_id = users.user_id
and user_plans_roles.role_id = users.role_id
-- exclude users without a matching role_id
where users.user_id is null
) missing_user_plan_roles
on user_plans.user_id = missing_user_plan_roles.user_id
and user_plans.plan_id = missing_user_plan_roles.plan_id
-- exclude missing roles
where missing_user_plan_roles.user_id is null
order by user_id, plan_id
--结果
使用SQL查找缺少计划角色的用户
select user_plans_roles.plan_id, user_plans_roles.user_id from (
-- get the result assuming user has all plans and roles
select distinct plan_id, user_id, plan_role.role_id
from plan_role, user_role
) user_plans_roles
left join user_role users
on user_plans_roles.user_id = users.user_id
and user_plans_roles.role_id = users.role_id
-- exclude users without a matching role_id
where users.user_id is null
返回
plan_id user_id
1 100
3 100
我的原文有点混乱,我已经更新了。对不起!基本上,我需要所有计划id,以便给定用户id的角色id集是计划id的角色id集的超集。该查询返回用户id 100的计划id 1、2和4。但是,plan_id 1具有用户没有的角色_id 30。因此,计划1的角色不是用户角色的子集。您将如何更改它以使其适用于多个特定用户?我没有足够准确地描述我的问题,并且已经更新了问题文本(很抱歉!)。我需要所有计划id,以便给定用户id的角色id集是计划id的角色id集的超集。
plan_id user_id
1 100
3 100