简化我在MySQL中有两个表:一个持有一个人实体和一个关系表,它将多个权利与个人实体相关联。表格如下:
人
person_id | person_name
1 | Michael
2 | Kevin
person2right
person_id | right_id
1 | 1
1 | 2
1 | 4
2 | 1
2 | 2
我现在想要实现的是让所有人都包括所有相关权利,这些权利至少具有已定义的权利 - 在此示例中为right_id 1和4。
到目前为止我所使用的是subselect的查询,但我想知道是否有更有效的方法来实现我的目标而没有subselect,因为MySQL在加入subselect时无法使用索引。这是我的疑问:
SELECT person_name, GROUP_CONCAT(`person2right`.`right_id`) as `all_rights`
FROM `person`
LEFT JOIN `person2right` ON `person`.`person_id` = `person2right`.`person_id`
LEFT JOIN (
SELECT `person_id` FROM `person2right` WHERE `right_id` IN (1, 4)
GROUP BY `person_id` HAVING COUNT(`person2right`.`right_id`) >= 2
) as `p2r` ON `person`.`person_id` = `p2r`.`person_id`
WHERE `p2r`.`person_id` IS NOT NULL GROUP BY `person_id`
也许某人有想法在没有子查询的情况下这样做。请帮助你。
提前谢谢!答案 0 :(得分:2)
这将仅选择具有权限1和权限4的人员(及其所有相关权利)。请注意,它与您的查询的不同之处在于您的查询选择所有人员(无论他们的权利如何)并且仅选择如果他们有权利1和4,他们的相关权利。
SELECT person_name, GROUP_CONCAT(`person2right`.`right_id`) as `all_rights`
FROM `person`
JOIN `person2right` ON `person`.`person_id` = `person2right`.`person_id`
GROUP BY `person`.`person_id`
HAVING SUM(`right_id` = 4) > 0 AND SUM(`right_id` = 1) > 0
修改:如果person2right
中的行是唯一的,那么您可以将having
子句更改为
HAVING SUM(`right_id` IN (1,4)) = 2
答案 1 :(得分:1)
让我们看看其他联接是否可以解决问题:
select person_name, group_concat(distinct p2r.right_id) as all_rights
from person as p
inner join person2right as p2r using (person_id) -- You don't need LEFT JOIN, because you'll only return persons with rights
-- The new stuff starts here: Two new LEFT JOINs to track the rights you want
left join person2right as p2r_1 using (person_id)
left join person2right as p2r_4 using (person_id)
where
-- Here is where you check if the rights exist
(p2r_1.right_id = 1 and p2r_4.right_id = 4)
group by p.person_id;
答案 2 :(得分:0)
您可以尝试检查where子句中的权限(避免第二次左连接)
...
WHERE 2 = (select count(*)
from person2right
where person_id = person.person_id
and right_id in (1, 4))