CREATE DEFINER = 'root'@'localhost'
PROCEDURE test.GetHierarchyUsers(IN StartKey INT)
BEGIN
-- prepare a hierarchy level variable
SET @hierlevel := 00000;
-- prepare a variable for total rows so we know when no more rows found
SET @lastRowCount := 0;
-- pre-drop temp table
DROP TABLE IF EXISTS MyHierarchy;
-- now, create it as the first level you want...
-- ie: a specific top level of all "no parent" entries
-- or parameterize the function and ask for a specific "ID".
-- add extra column as flag for next set of ID's to load into this.
CREATE TABLE MyHierarchy AS
SELECT U.ID
, U.Parent
, U.`name`
, 00 AS IDHierLevel
, 00 AS AlreadyProcessed
FROM
Users U
WHERE
U.ID = StartKey;
-- how many rows are we starting with at this tier level
-- START the cycle, only IF we found rows...
SET @lastRowCount := FOUND_ROWS();
-- we need to have a "key" for updates to be applied against,
-- otherwise our UPDATE statement will nag about an unsafe update command
CREATE INDEX MyHier_Idx1 ON MyHierarchy (IDHierLevel);
-- NOW, keep cycling through until we get no more records
WHILE @lastRowCount > 0
DO
UPDATE MyHierarchy
SET
AlreadyProcessed = 1
WHERE
IDHierLevel = @hierLevel;
-- NOW, load in all entries found from full-set NOT already processed
INSERT INTO MyHierarchy
SELECT DISTINCT U.ID
, U.Parent
, U.`name`
, @hierLevel + 1 AS IDHierLevel
, 0 AS AlreadyProcessed
FROM
MyHierarchy mh
JOIN Users U
ON mh.Parent = U.ID
WHERE
mh.IDHierLevel = @hierLevel;
-- preserve latest count of records accounted for from above query
-- now, how many acrual rows DID we insert from the select query
SET @lastRowCount := ROW_COUNT();
-- only mark the LOWER level we just joined against as processed,
-- and NOT the new records we just inserted
UPDATE MyHierarchy
SET
AlreadyProcessed = 1
WHERE
IDHierLevel = @hierLevel;
-- now, update the hierarchy level
SET @hierLevel := @hierLevel + 1;
END WHILE;
-- return the final set now
SELECT *
FROM
MyHierarchy;
-- and we can clean-up after the query of data has been selected/returned.
-- drop table if exists MyHierarchy;
END
それは面倒表示されることがありますが、これを使用するためには、
call GetHierarchyUsers(5);
を行う(または任意のキーIDあなたがのために階層ツリーをUP見つけたいです)。
前提は、使用している1つのキーから始めることです。その後、それをユーザーテーブルAGAINに参加するための基礎として使用しますが、最初のエントリのPARENT IDに基づいて行います。見つかったら、テンポラリテーブルを更新して、次のサイクルで再びそのキーの試行と参加をしないようにします。その後、親のIDキーが見つからなくなるまで続けてください。
これは、ネストの深さにかかわらず、親レコードまでの階層全体を返します。しかし、FINALの親だけが必要な場合は、@hierlevel変数を使って、追加されたファイル、またはORDER BYとLIMITの中の最新のものだけを返すことができます1
ビルKarwinが正しいです。 MySQLには 'CTE'を持っているので' SQL Server'のような再帰的なクエリのための関数はありません。再帰の振る舞いはまだシミュレートできます。 ':D' –
私はあなたが単一のクエリでMySQLで再帰を行うことはできないと思いますが、親エントリが見つからなくなるまで親レベルを探し続けるストアドプロシージャを使って同様の親階層クエリを実行しました。終了時に削除される一時テーブルを介して...それはあなたのために働くだろうか? – DRapp
@DRapp:それはおそらく受け入れられるでしょう。いずれかの方法を学ぶことは楽しいだろう –