2017-02-03 62 views
0

如何將此查詢轉換爲其等效的postgresql分層查詢? 如何在postgresql中替換CONNECT_BY_ISLEAF函數?將Oracle中的CONNECT_BY_ISLEAF替換爲Postgres

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) 

回答

1

遞歸查詢是在Postgres中使用遞歸的common table expression完成的。

您可以模擬Oracle的level只需遞增每個迭代的值,然後比較外部查詢中的值。

葉可以使用子查詢檢查 - 類似於MT0做

nocycle可以通過記住已處理所有行並添加where條件如果是停止遞歸部分來完成員工已經被處理。

通過通過各級攜帶初始EMP_ID,你也可以模仿甲骨文的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; 

在線例如:http://rextester.com/TSMVV17478

+0

這會否讓葉時可能會在不同的不同深度正確的葉子值層次結構樹的分支? – MT0

+0

@ MT0:可以修改它來處理這個問題。給定的例子只有一個分支(由於'where emp_id = 345',所以我沒有包括這個) –

+0

查詢正在管理樹中,因此可能有一個分支是'/ Manager/Team Lead/Worker'和另一個分支'/ Manager/Team Lead/Supervisor/Intern'既不是工人也不是實習生管理其他員工(也就是離職),但是處於不同的深度(並且具有相同的根部)。 – MT0

2

這是Oracle在使用遞歸子查詢因式分解(a.k.a.公用表表達式)中的等價物。它應該映射(也許在語法有些變化)到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條款 - 如果這是必要的,那麼你將需要建立一個機制來消除這些連接。)