0

我有一个用户 ID 值表,A 列有管理用户,B 列有用户。例如,我希望能够显示管理其他用户的用户列表。

用户 1 可以管理用户 2
用户 1 可以管理用户 3
用户 3 可以管理用户 4
用户 5 可以管理用户 6

这将产生下表:

--------------------------
| 管理用户 ID | 用户名 |
--------------------------
| 1 | 2 |
| 1 | 3 |
| 3 | 4 |
| 5 | 6 |
--------------------------

我想要一个查询或存储过程,通过按照层次结构来返回管理用户列表。因此,如果您是用户 1,则会输出以下列表。

1、2、3、4

然后,如果您是用户 2,那么您将只有 2 个输出。

2

然后,如果您是用户 5,则输出以下列表,依此类推。

5、6

鉴于我有每个用户 ID,实现这一目标的最佳方法是什么。

提前致谢。

4

3 回答 3

1

替换您的表名上的 YOUR_TABLE

DELIMITER $$

CREATE PROCEDURE get_users(IN base INT UNSIGNED)
BEGIN
DECLARE ids TEXT DEFAULT '';

SET @parents = base;
SET ids = base;

loop1: LOOP
    SET @stm = CONCAT(
        'SELECT GROUP_CONCAT(userId) INTO @parents FROM YOUR_TABLE',
        ' WHERE mgtuserId IN (', @parents, ')'
    );

    PREPARE fetch_childs FROM @stm;
    EXECUTE fetch_childs;
    DROP PREPARE fetch_childs;

    IF @parents IS NULL THEN LEAVE loop1; END IF;

    SET ids = CONCAT(ids, ',', @parents);
END LOOP;

SET @stm = CONCAT('(SELECT mgtuserId FROM YOUR_TABLE WHERE mgtuserId=',base,') UNION (SELECT userId FROM YOUR_TABLE WHERE userId IN (',ids, '))');

PREPARE fetch_childs FROM @stm;
EXECUTE fetch_childs;
DROP PREPARE fetch_childs;
END;

检查

CALL get_users(1);
1
2
3
4

并设置在 my.ini

thread_stack = 256K
于 2012-07-31T23:16:06.480 回答
0

给你一些搜索词:你正在寻找你的关系的传递闭包,这需要递归查询。据我所知,recursive 查询不能在 MySQL 中表达,除非借助存储过程或函数。

在搜索中使用上述某些术语将为您提供大量与您的问题密切相关的问题和答案。如何在 MySql 中使用递归查询?是其中之一。那里的答案链接到一个文档,该文档描述了一个PROCEDURE recursivesubtree可能是您实施的良好起点。

于 2012-07-31T22:19:22.537 回答
0

您的输出规范导致我所做的版本略有不同。

假设您没有任何“循环”,并且没有任何 mgtuserId = userId 的行,您可以通过多次将表连接到自身来模拟层次查询 N 级,如下所示:

SELECT n0.userId AS n0_userId
     , n1.userId AS n1_userId
     , n2.userId AS n2_userId
     , n3.userId AS n3_userId
     , n4.userId AS n4_userId
     , n5.userId AS n5_userId
     , n6.userId AS n6_userId
  FROM mytable n0
  LEFT JOIN mytable n1 ON n1.mgtuserId = n0.userId
  LEFT JOIN mytable n2 ON n2.mgtuserId = n1.userId
  LEFT JOIN mytable n3 ON n3.mgtuserId = n2.userId
  LEFT JOIN mytable n4 ON n4.mgtuserId = n3.userId
  LEFT JOIN mytable n5 ON n5.mgtuserId = n4.userId
  LEFT JOIN mytable n6 ON n6.mgtuserId = n5.userId
 WHERE n0.userId = 1

但是此查询不会返回您指定的结果集,即逗号分隔的列表。

此查询返回的每一行代表树下的“路径”,从指定的起点到每个叶节点(或者,在这种情况下,到每个深度不超过六层的节点(低于指定的起点)。

不,它不漂亮。但是您可以看到如何将其扩展到 N 个级别。

现在,我看不到将其转换为您指定的结果集的好方法。

我可能必须做同样的事情,但是使用单独的查询(一层深,两层深等)获取每个级别,然后使用 UNION ALL 将它们组合起来。但这会更难看。

为了得到每个叶节点的未指定数量的级别,我们确实需要使用一个临时表,并迭代地执行相同类型的查询。但当然,这不是一个单一的查询。

(我将研究一个返回您指定结果集的解决方案。)

于 2012-07-31T22:19:38.933 回答