动态处理生成的树

时间:2016-02-15 12:01:55

标签: sql postgresql

我们有以下树形结构。目的是使用postgresql查询在数据库中构造一个表。 该表应包含以下信息。第一列包含节点。  第二个包含父节点。

                  |--node1.1.1          
       |-node1.1--|                
       |          |--node1.1.2           
       |                
       |                
       |             
node1--|-node1.2--|--node1.2.1   
       |          
       |                
       |                
       |           
       |-node1.3              

表树:
enter image description here

下面是查找将生成初始表的查询:

CREATE TABLE tree
( node character varying NOT NULL,
  node_parent character varying,
  CONSTRAINT tree_pkey PRIMARY KEY (node),
  CONSTRAINT fk_ FOREIGN KEY (node_parent)
      REFERENCES tree (node) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tree
  OWNER TO postgres;

INSERT INTO tree(node, node_parent) VALUES ('node1', null);
INSERT INTO tree(node, node_parent) VALUES ('node1.1', 'node1');
INSERT INTO tree(node, node_parent) VALUES ('node1.2', 'node1');
INSERT INTO tree(node, node_parent) VALUES ('node1.3', 'node1');
INSERT INTO tree(node, node_parent) VALUES ('node1.1.1', 'node1.1');
INSERT INTO tree(node, node_parent) VALUES ('node1.1.2', 'node1.1');
INSERT INTO tree(node, node_parent) VALUES ('node1.2.1', 'node1.2');

然后从这个表(树)我们的目标是生成下表。查询应为每个组合节点返回子节点列表。此查询应生成与下面示例相同的结果。 为此,我们提出了以下查询。

SELECT node, node_parent   FROM tree t where   not (node  in(select distinct              node_parent from tree where  not node_parent is null))
union all
SELECT tn2.node, tn1.node_parent FROM tree tn1 join tree tn2 on tn1.node =     tn2.node_parent  where not tn1.node_parent is null and not (tn2.node  in(select      distinct node_parent from tree where  not node_parent is null))

结果:

enter image description here

我们提出的查询问题是它不是通用的,并不适用于所有情况(此查询仅适用于我们有一个深度等于3的树的情况)。我们想要一个适用于所有情况的查询。

3 个答案:

答案 0 :(得分:2)

看看with statement。您的最终查询将如下所示。

with recursive hierarchy(node, node_parent, level) as (
    select node, node_parent, 0
    from tree
    where node_parent is null
    union all
    select t.node, t.node_parent, level + 1
    from tree t
        join hierarchy h on t.node_parent = h.node)
select *
from hierarchy;

答案 1 :(得分:1)

使用标准sql无法创建具有可变深度的查询。

所以你可以按照以下方式之一:

  • 创建一个带有两个节点的函数,如果它们是亲属则返回true(所以如果可以从node1转到node2,父节点传递父节点。并在查询中使用此函数。

    < / LI>
  • 使用递归查询

  • 更改数据库而不是标准关系数据库使用图形数据库,该图形数据库本身可以提供函数来导航整个图形而不受深度限制。

请注意,前两个选项可能非常繁重,因为不会为此类查询编写关系数据库。

答案 2 :(得分:0)

感谢您的所有贡献。多亏了我们已成功解决了以下问题:

SELECT DISTINCT
    ml.list_id
   ,info_risk_code as c_rr
   ,list_risk_code as a_rr
FROM 
    my_list AS ml
    INNER JOIN my_info_list AS mil ON mil.list_id = ml.list_id
    INNER JOIN my_info AS mi ON mil.info_id = mi.info_id
WHERE 
    (
            (info_risk_code = '600' OR info_risk_code = '360') 
        AND (NOT list_risk_code = '600' AND NOT list_risk_code = '360')
    )
    OR 
    (
            (NOT info_risk_code = '600' AND NOT info_risk_code = '360') 
        AND (list_risk_code = '600' OR list_risk_code = '360')
    )