Mysql递归查询获取父类别

标签 mysql left-join recursive-query

我有 3 张 table :

  1. 用户
  2. 用户组
  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。我想要的是顶级组。

感谢您的帮助!

最佳答案

典型的解决方案是创建一个存储函数,通过跟踪起源直到找到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()

关于Mysql递归查询获取父类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42980923/

相关文章:

postgresql - 如何创建将父 ID 和祖 parent ID 插入数组的递归 CTE 查询

mysql - 从mysql数据库获取DateTime到android sqlite

mysql - phpMyAdmin 主键指示器在文本上显示为灰色

mysql:在大树中组织搜索

mysql - 需要查询自引用表以查找不是任何项目的父项的所有项目

MySql Recursive - 从给定的id获取所有 child 和 parent

mysql - 如何从 mysql 的得分表中获取每场比赛的 3 个第一名?

mysql - 将 RowDataPacket 记录合并为一个并返回 JSON

php - 减少左连接查询执行时间

php - MySQL 查找连接 3 个表