PostgreSQL 和过滤递归查询

PostgreSQL and filtered recursive query

在 Oracle 中可以使用子句 CONNECT BYSTART WITH 查询树。

例如:

SELECT RPAD (' ', (LEVEL - 1) * 4) || node_name AS node, LEVEL
  FROM hierarchy
  START WITH NVL (pig_ear_id, 0) = 0
  CONNECT BY PRIOR id = pig_ear_id;

可以简单地过滤查询结果以显示唯一被过滤谓词接受或位于根路径上的节点:

SELECT RPAD (' ', (LEVEL - 1) * 4) || node_name AS node, LEVEL
  FROM hierarchy
  START WITH NVL (pig_ear_id, 0) = 0
  CONNECT BY PRIOR id = pig_ear_id AND id IN (
                 SELECT id
                   FROM hierarchy
                   START WITH node_name = 'some-pattern'
                   CONNECT BY PRIOR pig_ear_id = id
               );

PostgreSQL 中类似的 select 将使用子句 WITH RECURSIVE ... 构建。据我了解,一个 with-query 不能包含在其他 with-query 中以获得与 Oracle 允许的相同的过滤结果。

如何在 PostgreSQL 中重写第二个 select?..

如果您有一个调用某个函数的 with 查询,而该函数又有一个 with 查询, 然后它允许我们并且不会引发任何错误......这样我们仍然能够嵌套查询。

所以我通常使用 with 子句创建查询。请参阅下面的第一个查询。 它的 in 子句中有 select 查询,即 selecting 记录 return 由函数 (my_function) 编辑。 并且该函数具有另一个带有查询的层次结构。

我也不知道你想从你的 query.so 更改查询中 return 什么,因为你 need.This 只是实现所需结构的方法。

以下是适用于任何其他数据库的 sql server.Change 的语法。

with alias_list
(
pig_ear_id,
node_name,
id
) as (
select pig_ear_id, node_name, id
  from hierarchy
 where pig_ear_id = ?
union all
select b.pig_ear_id, node_name, id
  from alias_list a, hierarchy b
 where a.pig_ear_id = b.id
   and id in (select id from my_function('some-pattern')))
select * from alias_list;

============================================= =================

create function my_function(@node_name   varchar(40))
returns @temptable table
(
   id varchar(40)
)
as
begin

with alias_list
(
pig_ear_id,
node_name,
id
) as (
select pig_ear_id, node_name, id
  from hierarchy
 where node_name = ?
union all
select b.pig_ear_id, node_name, id
  from alias_list a, hierarchy b
 where a.id = b.pig_ear_id)

insert into @temptable select * from alias_list;
return
end

============================================= ===================

As I understand one with-query can not be included in other with-query

当然可以,一个接一个地写:

with recursive valid_nodes as (

   -- this is the inner "CONNECT BY" query from your example
   select id 
   from hierarchy
   where node_name = 'some-pattern'
   union all
   select c.id
   from hierarchy c
     join valid_nodes p on c.id = p.pig_ear_id

), final_tree as (

   -- this is outer query from your example

   select node_name as node, 1 as level
   from hierarchy
   where NVL (pig_ear_id, 0) = 0

   union all

   select c.node_name, p.level + 1
   from hierarchy c
     join final_tree p on p.id = c.pig_ear_id
   where id in (select id from valid_nodes) -- and here we re-use the previous CTE

)
select rpad(node, level - 1)||node, level
from final_tree;

注意recursive关键字只需要在开头说明。不管你有多少递归 CTE(但你需要在 CTE 链中至少有一个,如果你使用它)。