0

ユーザーのID値の表があります列Aには管理ユーザーがあり、列Bにはユーザーがあります。たとえば、他のユーザーを管理しているユーザーの一覧を表示できるようにしたい。

ユーザー 1 はユーザー 2 を管理できます
ユーザー 1 はユーザー 3 を管理できます
ユーザー 3 はユーザー 4 を管理できます
ユーザー 5 はユーザー 6 を管理できます

これにより、次の表が生成されます。

--------------------------
| | mgtuserId | ユーザー 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

いくつかの検索用語を提供するには: リレーションの推移閉包を探していますが、これには再帰クエリが必要です。私の知る限り、ストアド プロシージャまたは関数を使用しない限り、再帰クエリを 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

しかし、このクエリは、指定した結果セット (カンマ区切りのリスト) を返しません。

このクエリが返す各行は、指定された開始点から各リーフ ノード (または、この場合は、6 レベル以下の深さ (指定された開始点より下) にあるすべてのノード) までの、ツリーを下る「パス」を表します。

いいえ、きれいではありません。しかし、これを N レベルに拡張できることがわかります。

現在、これを指定した結果セットに変換する良い方法がわかりません。

同じようなことをしなければならないかもしれませんが、各レベルを個別のクエリ (1 レベルの深さ、2 レベルの深さなど) で取得し、UNION ALL を使用してそれらを結合します。しかし、それはさらに醜いでしょう。

各リーフ ノードまで不特定数のレベルを取得するには、一時テーブルを使用して、これと同じ種類のクエリを繰り返し実行する必要があります。もちろん、それは単一のクエリではありません。

(指定された結果セットを返すソリューションに取り組みます。)

于 2012-07-31T22:19:38.933 に答える