如何将此查询转换为其等效的postgresql分层查询? 如何在postgresql中替换 CONNECT_BY_ISLEAF 函数?
SELECT emp_id,mgr_id,name,SYS_CONNECT_BY_PATH (name,'/') PATH ,CONNECT_BY_ISLEAF ISLEAF
FROM employee
START WITH (emp_id = 345)
CONNECT BY NOCYCLE (PRIOR emp_id = mgr_id)
答案 0 :(得分:2)
这在Oracle中使用递归子查询分解子句(a.k.a. Common Table Expression)等效。它应该映射(可能在语法上有一些变化)到PostgreSQL:
WITH cte ( emp_id, mgr_id, name, path, leaf ) AS (
SELECT emp_id,
mgr_id,
name,
'/' || name,
CASE WHEN EXISTS( SELECT 1 FROM employee m WHERE m.mgr_id = e.emp_id )
THEN 0 ELSE 1 END
FROM employee e
WHERE emp_id = 345
UNION ALL
SELECT e.emp_id,
e.mgr_id,
e.name,
c.path || '/' || e.name,
CASE WHEN EXISTS( SELECT 1 FROM employee m WHERE m.mgr_id = e.emp_id )
THEN 0 ELSE 1 END
FROM employee e
INNER JOIN cte c
ON( e.mgr_id = c.emp_id )
)
SELECT * FROM cte;
(注意:这不考虑分层查询的NOCYCLE
子句 - 如果这是必要的,那么您将需要构建一个机制来消除这些连接。) < / p>
答案 1 :(得分:2)
使用Postgres中的递归common table expression进行递归查询。
您可以通过简单地为每次迭代增加一个值然后在外部查询中比较它来模拟Oracle的level
。
可以使用子查询检查叶子 - 类似于MT0所做的
nocycle
可以通过记住已处理的所有行并向递归部分添加where条件来完成,如果已经处理了员工,则会停止。
通过在所有级别上运行初始emp_id,您还可以模拟Oracle的connect_by_root
with recursive cte (emp_id, mgr_id, name, path, level, visited, root_id) AS
(
select emp_id,
mgr_id,
name,
'/' || name,
1 as level,
array[emp_id] as visited,
emp_id as root_id
from employee e
where emp_id = 345
union all
select c.emp_id,
c.mgr_id,
c.name,
concat_ws('/', p.path, c.name),
p.level + 1,
p.visited || c.emp_id,
p.root_id
from employee c
join cte p on p.emp_id = c.mgr_id
where c.emp_id <> all(p.visited)
)
SELECT e.*,
not exists (select * from cte p where p.mgr_id = e.emp_id) as is_leaf
FROM cte e;