级联选择,直到所有父母在表

时间:2016-02-13 11:21:01

标签: mysql

在我的MySQL数据库中,我有一个名为units的表,其结构如下:

ID, Name, parentUnitID, UnitTypeID, ...

是否可以生成一个完整的单元链,其中包含一个查询和一个ID作为起点?只要给定ID有更多父级,就级联查询?在没有深度限制的情况下,我找不到生成此方法的方法。

给定的ID可能有一个父本身也有一个父母,也可能有一个,......等等。

编辑:

我期待的结果是这样的:

IDDepth1, IDDepth2, IDDepth3, ..., NameDepth1, NameDepth2, NameDepth3, ...

或者

UnitTypeID1, Name1,  
UnitTypeID2, Name2,  
UnitTypeID3, Name3,  
...

获取给定ID的完整Unit-Chain并在PHP中解析它以构建级联数组。

EDIT2:

我试过这样的事情

SELECT ID, Name
FROM Units as u1
WHERE UnitTypeID = "4"
AND EXISTS (
    SELECT ID, Name
    FROM Units as u2
    WHERE UnitTypeID = "5"
    AND u2.ParentUnitID = u1.ID
    AND EXISTS (
        SELECT ID
        FROM Units as u3
        WHERE ID = "1692820"
        AND u3.UnitTypeID = "6"
        AND u3.ParentUnitID = u2.ID
   )
);

但首先它是静态的,其次EXISTS的结果不是SELECT本身的一部分。

1 个答案:

答案 0 :(得分:0)

你可以通过编写一个存储过程来实现这个目的,它会将父母ID插入临时表并循环访问父母等等。

我写了以下程序作为一个简单的例子;这当然不是完美的,但可以是一个开始

DELIMITER $$

drop procedure if exists get_unitschain$$

CREATE PROCEDURE get_unitschain (IN childUnitID INTEGER)
BEGIN
    DROP TEMPORARY TABLE IF EXISTS tmp_chain; -- Will contain the parents ID's
    DROP TEMPORARY TABLE IF EXISTS tmp_processed; -- Copy of tmp_chain
    DROP TEMPORARY TABLE IF EXISTS tmp_parents; -- New parents identified by each WHILE loop

    CREATE TEMPORARY TABLE tmp_chain (
        ID INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
        UnitID INTEGER NOT NULL
    );

    CREATE TEMPORARY TABLE tmp_processed (
        UnitID INTEGER NOT NULL
    );

    CREATE TEMPORARY TABLE tmp_parents (
        UnitID INTEGER NOT NULL
    );

    INSERT INTO tmp_chain (UnitID) VALUES (childUnitId);
    INSERT INTO tmp_parents (UnitID) VALUES (childUnitId); -- To start the WHILE loop

    WHILE (SELECT COUNT(*) FROM tmp_parents) DO
        DELETE FROM tmp_parents;

        INSERT INTO tmp_parents (UnitID)
            SELECT units.parentUnitID 
                FROM tmp_chain
                    INNER JOIN units ON units.ID = tmp_chain.UnitId
                WHERE units.parentUnitID NOT IN (SELECT tmp_processed.UnitId FROM tmp_processed);

        INSERT INTO tmp_chain (UnitID) SELECT tmp_parents.UnitID FROM tmp_parents;
        INSERT INTO tmp_processed (UnitID) SELECT tmp_parents.UnitID FROM tmp_parents;
    END WHILE;

    SELECT units.UnitTypeID, units.Name FROM tmp_chain INNER JOIN units ON units.ID = tmp_chain.UnitID;

    DROP TEMPORARY TABLE tmp_chain;
    DROP TEMPORARY TABLE tmp_processed;
    DROP TEMPORARY TABLE tmp_parents;
END$$

使用该程序:

CALL get_unitschain([child id]);