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

MySQL-隣接リストモデル-深さを取得

    これは完全に陽気です。昨日、同様の質問で+50の賞金を獲得しました: MySQLクエリを使用して行をトラバースし、再帰ツリーを作成します

    DBAStackExchangeのストアドプロシージャを使用してこれを行う方法 を参照しました (2011年10月24日)

    DBA StackExchangeの回答の例と同じストアドプロシージャを投稿します:

    任意のノードの親を取得するためのコード

    DELIMITER $$
    DROP FUNCTION IF EXISTS `junk`.`GetParentIDByID` $$
    CREATE FUNCTION `junk`.`GetParentIDByID` (GivenID INT) RETURNS INT
    DETERMINISTIC
    BEGIN
        DECLARE rv INT;
    
        SELECT IFNULL(parent_id,-1) INTO rv FROM
        (SELECT parent_id FROM pctable WHERE id = GivenID) A;
        RETURN rv;
    END $$
    DELIMITER ;
    

    任意のノードの祖先を取得するためのコード

    DELIMITER $$
    DROP FUNCTION IF EXISTS `junk`.`GetAncestry` $$
    CREATE FUNCTION `junk`.`GetAncestry` (GivenID INT) RETURNS VARCHAR(1024)
    DETERMINISTIC
    BEGIN
        DECLARE rv VARCHAR(1024);
        DECLARE cm CHAR(1);
        DECLARE ch INT;
    
        SET rv = '';
        SET cm = '';
        SET ch = GivenID;
        WHILE ch > 0 DO
            SELECT IFNULL(parent_id,-1) INTO ch FROM
            (SELECT parent_id FROM pctable WHERE id = ch) A;
            IF ch > 0 THEN
                SET rv = CONCAT(rv,cm,ch);
                SET cm = ',';
            END IF;
        END WHILE;
        RETURN rv;
    END $$
    DELIMITER ;
    

    任意のノードの家系図(または子孫)を取得するためのコード

    DELIMITER $$
    
    DROP FUNCTION IF EXISTS `junk`.`GetFamilyTree` $$
    CREATE FUNCTION `junk`.`GetFamilyTree` (GivenID INT) RETURNS varchar(1024) CHARSET latin1
    DETERMINISTIC
    BEGIN
    
        DECLARE rv,q,queue,queue_children VARCHAR(1024);
        DECLARE queue_length,front_id,pos INT;
    
        SET rv = '';
        SET queue = GivenID;
        SET queue_length = 1;
    
        WHILE queue_length > 0 DO
            SET front_id = FORMAT(queue,0);
            IF queue_length = 1 THEN
                SET queue = '';
            ELSE
                SET pos = LOCATE(',',queue) + 1;
                SET q = SUBSTR(queue,pos);
                SET queue = q;
            END IF;
            SET queue_length = queue_length - 1;
    
            SELECT IFNULL(qc,'') INTO queue_children
            FROM (SELECT GROUP_CONCAT(id) qc
            FROM pctable WHERE parent_id = front_id) A;
    
            IF LENGTH(queue_children) = 0 THEN
                IF LENGTH(queue) = 0 THEN
                    SET queue_length = 0;
                END IF;
            ELSE
                IF LENGTH(rv) = 0 THEN
                    SET rv = queue_children;
                ELSE
                    SET rv = CONCAT(rv,',',queue_children);
                END IF;
                IF LENGTH(queue) = 0 THEN
                    SET queue = queue_children;
                ELSE
                    SET queue = CONCAT(queue,',',queue_children);
                END IF;
                SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
            END IF;
        END WHILE;
    
        RETURN rv;
    
    END $$
    

    すべての実行を示すために、ここにサンプルデータがあります

    USE junk
    DROP TABLE IF EXISTS pctable;
    CREATE TABLE pctable
    (
        id INT NOT NULL AUTO_INCREMENT,
        parent_id INT,
        PRIMARY KEY (id)
    ) ENGINE=MyISAM;
    INSERT INTO pctable (parent_id) VALUES (0);
    INSERT INTO pctable (parent_id) SELECT parent_id+1 FROM pctable;
    INSERT INTO pctable (parent_id) SELECT parent_id+2 FROM pctable;
    INSERT INTO pctable (parent_id) SELECT parent_id+3 FROM pctable;
    INSERT INTO pctable (parent_id) SELECT parent_id+4 FROM pctable;
    INSERT INTO pctable (parent_id) SELECT parent_id+5 FROM pctable;
    SELECT * FROM pctable;
    

    これがすべての親、家系図、家系図を表示するためのクエリです

    SELECT
        id,parent_id,
        GetParentIDByID(id),
        GetAncestry(id),
        GetFamilyTree(id)
    FROM pctable;
    

    試してみてください!!!



    1. SQLのTCLコマンド

    2. MySQLでストアドプロシージャをバックアップする方法

    3. MYSQL-LEFTJOINの行が存在しない場合にのみ選択します

    4. PostgreSQLバックアップが適切かどうかはどうすればわかりますか?