Mysql 递归查询获取父类别
Mysql recursive query to get parent category
我有 3 个 table:
- 用户
- user_groups
- 组
一个用户可以在多个(子)组中。它们存储在 user_groups
table 中,像这样
+--------------+--------------+---------------+
| id | user_id | group_id |
+--------------+--------------+---------------+
| 1 | 1 | 23 |
+--------------+--------------+---------------+
| 2 | 2 | 24 |
-----------------------------------------------
现在在我的 groups
table 中,排名靠前的类别是 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 |
+--------------+--------------+---------------+
现在我想构建一个查询,为我提供所有用户的所有父组。我做了一些关于递归查询的研究,我发现了这个特殊的 post:
How to create a MySQL hierarchical recursive query
但是我不知道加入 tables 后应该如何处理这个问题。
这是我目前得到的:
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。我要的是顶级群
感谢您的帮助!
典型的解决方案是创建一个存储函数,通过跟踪父系直到找到 parent_id = 0 的行,returns 任何给定组的顶级组。
然后您可以将该函数应用于用户所属的每个组,以及 select 不同的顶级组集。
像这样的东西应该适合你:
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()
我有 3 个 table:
- 用户
- user_groups
- 组
一个用户可以在多个(子)组中。它们存储在 user_groups
table 中,像这样
+--------------+--------------+---------------+
| id | user_id | group_id |
+--------------+--------------+---------------+
| 1 | 1 | 23 |
+--------------+--------------+---------------+
| 2 | 2 | 24 |
-----------------------------------------------
现在在我的 groups
table 中,排名靠前的类别是 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 |
+--------------+--------------+---------------+
现在我想构建一个查询,为我提供所有用户的所有父组。我做了一些关于递归查询的研究,我发现了这个特殊的 post: How to create a MySQL hierarchical recursive query
但是我不知道加入 tables 后应该如何处理这个问题。
这是我目前得到的:
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。我要的是顶级群
感谢您的帮助!
典型的解决方案是创建一个存储函数,通过跟踪父系直到找到 parent_id = 0 的行,returns 任何给定组的顶级组。
然后您可以将该函数应用于用户所属的每个组,以及 select 不同的顶级组集。
像这样的东西应该适合你:
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()