我有3张桌子:
用户可以在多个(子)组中。它们存储在user_groups
表中,就像这样
+--------------+--------------+---------------+
| id | user_id | group_id |
+--------------+--------------+---------------+
| 1 | 1 | 23 |
+--------------+--------------+---------------+
| 2 | 2 | 24 |
-----------------------------------------------
现在在我的groups
表格中,排名靠前的是parent_id = 0
+--------------+--------------+---------------+
| id | parent_id | name |
+--------------+--------------+---------------+
| 1 | 2 | Group 1.1 |
+--------------+--------------+---------------+
| 2 | 0 | Group 1 |
+--------------+--------------+---------------+
| 3 | 2 | Group 1.2 |
+--------------+--------------+---------------+
| 4 | 3 | Group 1.2.1 |
+--------------+--------------+---------------+
| 5 | 2 | Group 1.3 |
+--------------+--------------+---------------+
现在我想构建一个查询,它为我提供了所有用户的所有父组。我做了一些关于递归查询的研究,我找到了这个特别的帖子: How to create a MySQL hierarchical recursive query
但是当我加入桌子时,我不知道如何处理这个问题。
这是我到目前为止所得到的:
SELECT
`users`.`id`,
`users`.`first_name`,
`users`.`last_name`,
`users`.`email`,
`users`.`language`,
`groups`.`name`,
`groups`.`parent_id`
FROM `users`
LEFT JOIN `user_groups`
ON `user_groups`.`user_id` = `users`.`id`
LEFT JOIN `groups`
ON `groups`.`id` = `user_groups`.`group_id`
WHERE
`users`.`created`
BETWEEN
DATE_SUB(NOW(), INTERVAL 365 DAY) AND NOW()
但是这个查询只能得到子组的名称和id。我想要的是顶级组。
感谢您的帮助!
答案 0 :(得分:1)
典型的解决方案是创建一个存储函数,通过跟踪父项,直到找到parent_id = 0的行,返回任何给定组的顶级组。
然后,您可以将该功能应用于用户所属的每个组,并选择一组不同的顶级组。
这样的事情对你有用:
delimiter $$
drop function if exists get_top_level_group_id $$
create function get_top_level_group_id (p_group_id int) returns int
begin
declare v_return_val int;
declare v_group_id int;
declare v_parent_id int;
declare continue handler for not found
begin
return -1;
end;
set v_group_id = p_group_id;
set v_parent_id = p_group_id;
while v_parent_id != 0
do
set v_group_id = v_parent_id;
select `parent_id`
into v_parent_id
from `groups`
where id = v_group_id;
end while;
return v_group_id;
end $$
delimiter ;
然后,您可以像这样更新您的查询,以获取这些用户及其不同的顶级群组:
SELECT DISTINCT
`users`.`id`,
`users`.`first_name`,
`users`.`last_name`,
`users`.`email`,
`users`.`language`,
get_top_level_group_id(`user_groups`.`group_id`) as top_level_group_id
FROM `users`
LEFT JOIN `user_groups`
ON `user_groups`.`user_id` = `users`.`id`
WHERE
`users`.`created`
BETWEEN
DATE_SUB(NOW(), INTERVAL 365 DAY) AND NOW()