MySQL JOIN / UNION DISTINCT 问题
MySQL JOIN / UNION DISTINCT issue
我正在做一个项目,用户需要根据他们所连接的部门获得权限。
所以现在我正在尝试做一个查询,根据用户 department_id 向我显示拥有所有必要权限的用户(结果中不会显示没有所有必要权限的用户) .
我一直在尝试很多不同的事情(不同类型的 JOINS、子查询 w/where in、exists 和 union distinct)但运气不佳,这种查询对我来说是下一个级别并挑战我的逻辑思维.
表格:
users
id
first_name
last_name
department_id
permissions
id
name
departments (relation to groups and categories based on department)
id
name
category_id
group_id
categories
id
name
groups
id
name
departments_permissions (permission requirement)
department_id
permission_id
categories_permissions (permission requirement)
category_id
permission_id
groups_permissions (permission requirement)
group_id
permission_id
users_permissions (users have permissions here)
user_id
permission_id
部门
- 一个部门可以(不需要)有很多权限(departments_permissions)。
- 一个部门可以(不需要)有一个类别。
- 一个部门可以(不需要)有一个组。
类别
- 一个类别 CAN(不需要)有很多权限(categories_permissions)。
组
- 一组CAN(不需要)有很多权限(groups_permissions)。
重要旁注
departments_permissions、categories_permissions 和 groups_permissions 可以包含一个或多个相同的 permission_id,因此我们必须 select 不同的值。
示例数据
我最近的查询尝试:
SELECT
`users`.id,
`users`.first_name,
`users`.last_name,
`users`.department_id
FROM
`users`
INNER JOIN
`departments` ON `users`.department_id = `departments`.id
INNER JOIN
`users_permissions` ON `users`.id = `users_permissions`.user_id
INNER JOIN
(
SELECT permission_id FROM departments_permissions WHERE department_id = departments.id
UNION DISTINCT
SELECT permission_id FROM categories_permissions WHERE category_id = departments.group_id
UNION DISTINCT
SELECT permission_id FROM groups_permissions WHERE group_id = departments.group_id
) AS tblPermissionsRequired ON `users_permissions`.permission_id = `tblPermissionsRequired`.permission_id
GROUP BY
`users_permissions`.user_id;
我想你需要的是这样的:
SELECT u.first_name,u.last_name,p.name
FROM users u, user_permissions up, permissions p
WHERE u.id=up.user_id AND
up.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, departments_permission dp, permissions p
WHERE u.department_id=d.id
AND d.id=dp.department_id
AND dp.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, categories_permission cp, permissions p
WHERE u.department_id=d.id
AND d.category_id=cp.category_id
AND cp.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, groups_permission gp, permissions p
WHERE u.department_id=d.id
AND d.group_id=gp.group_id
AND gp.permission_id=p.id
这里有一个提示:
- 使用上面的查询创建一个视图
- 在视图上执行 SELECT DISTINCT *
建立2个表(子查询)列出
- 用户需要的所有权限(即user_permissions)
- 用户拥有的所有权限(即与您所做的类似的 3 个联合)
加入他们并按 id 分组将找到所需的数量以及已经给出的数量。
最后,添加一个过滤子句(使用HAVING)。然后你得到了用户 ID 列表:)
select
up.user_id,
max(u.first_name) as first_name,
max(u.last_name) as last_name,
count(up.permission_id) as permission_required,
count(perm.permission_id) as permission_have
from
users u
join
users_permissions up on u.id = up.user_id
left join
(
SELECT users.id as user_id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN departments_permissions on departments_permissions.department_id = departments.id
UNION
SELECT users.id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN categories_permissions on categories_permissions.category_id = departments.category_id
UNION
SELECT users.id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN groups_permissions on groups_permissions.group_id = groups_permissions.group_id
) perm
on up.user_id = perm.user_id and up.permission_id = perm.permission_id
group by up.user_id
having count(up.permission_id) = count(perm.permission_id)
下面的脚本应该可以工作-
SELECT A.id,A.first_name,A.last_name,A.department_id
FROM
(
SELECT U.*,
A.Dept_id AS Dept_ID,
A.permission_id AS [Dept_Wise_Permissiion_List],
UP.permission_id
FROM users U
INNER JOIN (
SELECT D.id Dept_id,CP.permission_id
FROM departments D INNER JOIN categories_permissions CP ON D.category_id = CP.category_id
UNION ALL
SELECT D.id Dept_id,GP.permission_id
FROM departments D INNER JOIN groups_permissions GP ON D.group_id = GP.group_id
UNION ALL
SELECT D.id Dept_id, DP.permission_id
FROM departments D INNER JOIN departments_permissions DP ON D.id = DP.department_id
) A ON U.department_id =A. Dept_id
LEFT JOIN users_permissions UP
ON U.id = UP.user_id AND A.permission_id = UP.permission_id
)A
GROUP BY A.id,A.first_name,A.last_name,A.department_id
HAVING COUNT(ISNULL(A.permission_id,1)) = COUNT(A.permission_id)
我正在做一个项目,用户需要根据他们所连接的部门获得权限。
所以现在我正在尝试做一个查询,根据用户 department_id 向我显示拥有所有必要权限的用户(结果中不会显示没有所有必要权限的用户) .
我一直在尝试很多不同的事情(不同类型的 JOINS、子查询 w/where in、exists 和 union distinct)但运气不佳,这种查询对我来说是下一个级别并挑战我的逻辑思维.
表格:
users
id
first_name
last_name
department_id
permissions
id
name
departments (relation to groups and categories based on department)
id
name
category_id
group_id
categories
id
name
groups
id
name
departments_permissions (permission requirement)
department_id
permission_id
categories_permissions (permission requirement)
category_id
permission_id
groups_permissions (permission requirement)
group_id
permission_id
users_permissions (users have permissions here)
user_id
permission_id
部门
- 一个部门可以(不需要)有很多权限(departments_permissions)。
- 一个部门可以(不需要)有一个类别。
- 一个部门可以(不需要)有一个组。
类别
- 一个类别 CAN(不需要)有很多权限(categories_permissions)。
组
- 一组CAN(不需要)有很多权限(groups_permissions)。
重要旁注
departments_permissions、categories_permissions 和 groups_permissions 可以包含一个或多个相同的 permission_id,因此我们必须 select 不同的值。
示例数据
我最近的查询尝试:
SELECT
`users`.id,
`users`.first_name,
`users`.last_name,
`users`.department_id
FROM
`users`
INNER JOIN
`departments` ON `users`.department_id = `departments`.id
INNER JOIN
`users_permissions` ON `users`.id = `users_permissions`.user_id
INNER JOIN
(
SELECT permission_id FROM departments_permissions WHERE department_id = departments.id
UNION DISTINCT
SELECT permission_id FROM categories_permissions WHERE category_id = departments.group_id
UNION DISTINCT
SELECT permission_id FROM groups_permissions WHERE group_id = departments.group_id
) AS tblPermissionsRequired ON `users_permissions`.permission_id = `tblPermissionsRequired`.permission_id
GROUP BY
`users_permissions`.user_id;
我想你需要的是这样的:
SELECT u.first_name,u.last_name,p.name
FROM users u, user_permissions up, permissions p
WHERE u.id=up.user_id AND
up.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, departments_permission dp, permissions p
WHERE u.department_id=d.id
AND d.id=dp.department_id
AND dp.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, categories_permission cp, permissions p
WHERE u.department_id=d.id
AND d.category_id=cp.category_id
AND cp.permission_id=p.id
UNION
SELECT u.first_name,u.last_name,p.name
FROM users u, departments d, groups_permission gp, permissions p
WHERE u.department_id=d.id
AND d.group_id=gp.group_id
AND gp.permission_id=p.id
这里有一个提示:
- 使用上面的查询创建一个视图
- 在视图上执行 SELECT DISTINCT *
建立2个表(子查询)列出
- 用户需要的所有权限(即user_permissions)
- 用户拥有的所有权限(即与您所做的类似的 3 个联合)
加入他们并按 id 分组将找到所需的数量以及已经给出的数量。
最后,添加一个过滤子句(使用HAVING)。然后你得到了用户 ID 列表:)
select
up.user_id,
max(u.first_name) as first_name,
max(u.last_name) as last_name,
count(up.permission_id) as permission_required,
count(perm.permission_id) as permission_have
from
users u
join
users_permissions up on u.id = up.user_id
left join
(
SELECT users.id as user_id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN departments_permissions on departments_permissions.department_id = departments.id
UNION
SELECT users.id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN categories_permissions on categories_permissions.category_id = departments.category_id
UNION
SELECT users.id, permission_id
FROM users
INNER JOIN departments ON users.department_id = departments.id
INNER JOIN groups_permissions on groups_permissions.group_id = groups_permissions.group_id
) perm
on up.user_id = perm.user_id and up.permission_id = perm.permission_id
group by up.user_id
having count(up.permission_id) = count(perm.permission_id)
下面的脚本应该可以工作-
SELECT A.id,A.first_name,A.last_name,A.department_id
FROM
(
SELECT U.*,
A.Dept_id AS Dept_ID,
A.permission_id AS [Dept_Wise_Permissiion_List],
UP.permission_id
FROM users U
INNER JOIN (
SELECT D.id Dept_id,CP.permission_id
FROM departments D INNER JOIN categories_permissions CP ON D.category_id = CP.category_id
UNION ALL
SELECT D.id Dept_id,GP.permission_id
FROM departments D INNER JOIN groups_permissions GP ON D.group_id = GP.group_id
UNION ALL
SELECT D.id Dept_id, DP.permission_id
FROM departments D INNER JOIN departments_permissions DP ON D.id = DP.department_id
) A ON U.department_id =A. Dept_id
LEFT JOIN users_permissions UP
ON U.id = UP.user_id AND A.permission_id = UP.permission_id
)A
GROUP BY A.id,A.first_name,A.last_name,A.department_id
HAVING COUNT(ISNULL(A.permission_id,1)) = COUNT(A.permission_id)