sql >> データベース >  >> RDS >> Mysql

再帰的なmysqlselect?

    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を検索します。)

    前提は、作業している1つのKEYから始めることです。次に、それをベースとしてusersテーブルに再度参加しますが、最初のエントリのPARENTIDに基づいています。見つかったら、次のサイクルでそのキーに再度参加しないように一時テーブルを更新します。次に、「親」IDキーが見つからなくなるまで続行します。

    これにより、ネストの深さに関係なく、レコードの階層全体が親に返されます。ただし、FINALの親のみが必要な場合は、@ hierlevel変数を使用して、追加されたファイル内の最新の親のみを返すか、ORDERBYおよびLIMIT1を返すことができます



    1. 複数行のMySQLONDUPLICATE KEY UPDATEは、単一のクエリに挿入されます

    2. MySQLSETデータ型をPostgresに変換します

    3. すべてのニュースとすべてのコメントを取得する

    4. 解決方法認証プラグイン'caching_sha2_password'の問題を読み込めません