0

データ入力形式は次のとおりです。

+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| parent_id | int(10) unsigned | NO   |     | NULL    |       |
| child_id  | int(10) unsigned | NO   |     | NULL    |       |
+-----------+------------------+------+-----+---------+-------+

このデータは、DOT スクリプトを使用して、ツリー グラフの描画に使用される関係を定義します。DOT は、すべてのノード間のリンクが与えられた場合にすべての再帰を処理するのに十分なほど洗練されています。

1 -> 2;
1 -> 3;
2 -> 4;
4 -> 5;
4 -> 6;
6 -> 7;

生成します:

ここに画像の説明を入力

ブラックリスト配列で定義されたブランチを除外する必要があります。たとえば、ブラックリスト配列が[4]DOT スクリプトの場合、次のようにする必要があります。

1 -> 2;
1 -> 3;
2 -> 4;
4

2 に答える 2

1

お使いの DBMS が再帰クエリをサポートしている場合は、再帰クエリによってツリーをトリミングできます (ビューまたは関数に入れることもできます)。この例は Postgres で機能しますが、MS または Oracle に適用できます。

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE family
        ( parent_id INTEGER NOT NULL
        , child_id INTEGER NOT NULL
        , PRIMARY KEY (parent_id,child_id)
        );

INSERT INTO family(parent_id,child_id) VALUES
 (1 , 2) ,(1 , 3)
,(2 , 4)
,(4 , 5) ,(4 , 6)
,(6 , 7)
        ;

CREATE TABLE black_sheep (id INTEGER NOT NULL PRIMARY KEY);
INSERT INTO black_sheep(id) VALUES(4);
-- INSERT INTO black_sheep(id) VALUES(6);

WITH RECURSIVE tree AS (
        SELECT parent_id AS opa
                , parent_id as dad
                , child_id AS kid
        FROM family f0
        WHERE NOT EXISTS (
                SELECT *
                FROM family nx
                WHERE nx.child_id = f0.parent_id
                )
        UNION ALL
        SELECT tr.opa AS opa
                , f1.parent_id AS dad
                , f1.child_id AS kid
        FROM family f1
        JOIN tree tr ON tr.kid = f1.parent_id
        WHERE NOT EXISTS (
                SELECT *
                FROM black_sheep nx
                WHERE nx. id = f1.parent_id
                )
        )
SELECT * FROM tree;

結果:

 opa | dad | kid 
-----+-----+-----
   1 |   1 |   2
   1 |   1 |   3
   1 |   2 |   4
(3 rows)
于 2012-12-22T13:57:35.407 に答える
0

これは、私が思いついた最も効率的なアプローチです。

$relations  = $db->query("SELECT `parent_id`, `child_id` FROM `relations` ORDER BY `parent_id` ASC LIMIT 500;")->fetchAll(PDO::FETCH_ASSOC);

function filterALMData ($data, array $exclude) {
    while (count($exclude)) {
        $new_exclude = [];
        foreach ($data as $i => $node) {
            if (in_array($node['parent_id'], $exclude)) {               
                $new_exclude[] = $node['child_id'];
                unset($data[$i]);
            }
        }
        $exclude = $new_exclude;
    }
    return $data;
};


$data = filterALMData($relations, [4]);

これを投稿して、これまでに試したことを示します。好意的な回答ではありません。

于 2012-12-22T12:58:15.333 に答える