【问题标题】:Multi-item Path Query with PostgreSQL使用 PostgreSQL 进行多项目路径查询
【发布时间】:2013-01-04 19:02:45
【问题描述】:

使用以下 PostgreSQL 9.2.2 表:

  id    | parent_id
--------+----------
 body   | null
 head   | body
 mouth  | head
 eye    | head
 tooth  | mouth
 tongue | mouth
 sclera | eye
 cornea | eye

我需要一个输出,其中列出每个非父母子女的所有直接间接父母,例如:

tooth   mouth
tooth   head
tooth   body
tongue  mouth
tongue  head
tongue  body
sclera  eye
sclera  head
sclera  body
cornea  eye
cornea  head
cornea  body

我尝试过搜索,我的结果只显示了使用 with-recursive 的单项查询,例如:

WITH RECURSIVE t AS ( 
SELECT  parent_id, id 
FROM    item_tree 
WHERE   child_id = id 
UNION ALL 
SELECT  it.parent_id, it.id
    FROM    item_tree it 
JOIN    t 
ON  it.child_id = t.parent_id
) 
SELECT  id, child_id 
FROM    t 

我可以在外部编写一个循环,每次都替换id,但只能在 SQL 中完成吗?

@丹尼尔,

这是原始查询的输出:

  id     parent_id
  ------ ---------
  cornea eye
  cornea NULL
  cornea head
  cornea body
  sclera eye
  sclera head
  sclera NULL
  sclera body
  tongue body
  tongue head
  tongue NULL
  tongue mouth
  tooth  body
  tooth  head
  tooth  mouth
  tooth  NULL 

然而,如果你用一个空过滤的选择语句将它括起来,即使你删除了内部的空过滤器,它也会给出所需的结果,如下所示:

  select * from (
     WITH RECURSIVE t(id,parent_id) AS ( 
     select id,parent_id from item_tree i
     UNION ALL
     select t.id,i.parent_id from item_tree i JOIN t on i.id=t.parent_id 
     )
     select * from t order by id
  ) t1 where parent_id is not null;

无论如何,我已经点击了复选标记,因为这可能是一个错误(我尝试通过 jdbc 和在 pgAdmin3 中运行两个查询,并具有相同的输出)

【问题讨论】:

    标签: sql postgresql common-table-expression recursive-query


    【解决方案1】:

    假设表的结构是 item_tree (id text, parent_id text),递归查询可以从您定义的叶子元素开始(即不是任何东西的父元素) ),并且具有 null parent_id 的顶级元素也必须被过滤:

    select id,parent_id from item_tree i
     where parent_id is not null and
      id not in  (select parent_id from item_tree where parent_id is not null)
    

    然后将 (parent_id,id) 关系爬到树的顶部。

    完整查询:

    WITH RECURSIVE t(id,parent_id) AS ( 
    select id,parent_id from item_tree i where parent_id is not null 
       and id not in  (select parent_id from item_tree where parent_id is not null)
    UNION ALL
     select t.id,i.parent_id from item_tree i JOIN t on i.id=t.parent_id 
    )
    select * from t order by id;
    

    编辑: 上述查询在其输出中包含层次结构顶部的 NULL。为了排除它们,可以改用这个修改后的版本。最终结果应该与带有外部过滤的已编辑问题中的查询相同。

    WITH RECURSIVE t(id,parent_id) AS ( 
    select id,parent_id from item_tree i where parent_id is not null 
       and id not in  (select parent_id from item_tree where parent_id is not null)
    UNION ALL
     select t.id,i.parent_id from item_tree i JOIN t on i.id=t.parent_id
       where i.parent_id is not null 
    )
    select * from t order by id;
    

    【讨论】:

    • 谢谢。这是我需要的脚本,但空过滤器似乎不起作用;使用 select-parent_id-null 过滤器封闭递归查询。我希望你不会介意编辑你的代码,所以我可以点击你答案上的复选标记:))
    猜你喜欢
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    相关资源
    最近更新 更多