数据输入格式为:
+-----------+------------------+------+-----+---------+-------+
| 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;
答案 0 :(得分: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)
答案 1 :(得分: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]);
我发帖说明我到目前为止所尝试的内容。这不是一个好的答案。