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 回答