2017-02-03 13 views
0

Как преобразовать этот запрос в его эквивалентный иерархический запрос postgresql? Как заменить CONNECT_BY_ISLEAF функция в postgresql?Заменить CONNECT_BY_ISLEAF в Oracle на 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

Рекурсивные запросы выполняются с использованием рекурсивного common table expression в Postgres.

Вы можете имитировать Oracle level, просто увеличивая значение для каждой итерации, а затем сравнивая это во внешнем запросе.

Лист можно проверить с помощью вложенного запроса - по аналогии с тем, что mt0 сделал

nocycle можно сделать, помня все строки, которые были обработаны и добавление где условия рекурсивной части, которая останавливается, если сотрудник уже обработан.

Выполняя первоначальную 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; 

Online пример Оракула: 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 с использованием рекурсивного пункт факторинга Суб-запроса (а.к.а. Общие Таблица 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 - если это необходимо, то вам нужно будет построить в механизм для устранения этих объединений.)