2016-05-30 12 views
1

Мне нужна небольшая помощь в иерархическом SQL-запросе Informix. У меня есть таблица со следующей структурой:Для любого дочернего элемента в иерархии, выберите полное дерево по иерархии INFORMIX SQL

create table empl_relation (
employee_id char(10), 
manager_id char(10)); 

employee_id  | manager_id 
5148    null    
5149    5148 
5150    5149 
5151    5148 
5152    5151 
5154    5148 
5155    5154 

Я смог успешно выполнить следующий запрос:

SELECT employee_id, manager_id FROM empl_relation 
    START WITH employee_id = 5148 
    CONNECT BY PRIOR employee_id = manager_id 
    ORDER SIBLINGS BY employee_id; 

который возвращает точную иерархию, как указано в таблице выше. Тем не менее, я пытаюсь добиться чего-то другого. Я пытаюсь получить тот же результат, заданный в качестве идентификатора сотрудника в иерархии. Например, в запросе, если я укажу 5154 как вход employee_id, я должен иметь возможность получить всех родителей и их детей, а также детей и внуков входного идентификатора сотрудника. Если быть точным, я хочу получить тот же результат, что и я, выполнив указанный выше запрос.

Можно ли достичь в одном запросе? Если да, можете ли вы мне помочь в достижении этого?

      EDIT 

Хорошо, я понял, один из способов достижения этой цели, но она включает в себя выполнение 2 запросов следующим образом:

SELECT employee_id, manager_id FROM empl_relation 
    START WITH employee_id = 5150 
    CONNECT BY employee_id = PRIOR manager_id 
    ORDER SIBLINGS BY employee_id ; 

который будет возвращать:

employee_id  | manager_id 
5148  
5149     5148 
5150     5149 

Тогда мы можем получить parent employee_id на уровне приложения, выполнив итерацию с помощью набора результатов, а затем выполнив следующий запрос, чтобы получить полное иерархическое дерево:

SELECT employee_id, manager_id FROM empl_relation 
    START WITH employee_id = 5148 
    CONNECT BY PRIOR employee_id = manager_id 
    ORDER SIBLINGS BY employee_id; 

Это будет нормально работать, но было бы здорово, если бы я смог достичь этого в одном запросе.

ответ

2

Вдохновленный ответ Джонатана, я придумал немного сокращенный вариант его запрос выглядит следующим образом:

SELECT employee_id,manager_id FROM empl_relation 
START WITH employee_id = 
(SELECT employee_id 
    FROM empl_relation er 
    WHERE er.manager_id IS NULL 
    START WITH employee_id = 5150 CONNECT BY employee_id = 
    PRIOR manager_id) 
CONNECT BY 
PRIOR employee_id = manager_id 
ORDER BY employee_id; 

Это также работает нормально.

+1

Я был уверен, что должен быть более сжатый способ сделать это, но я получал синтаксические ошибки на них. Отлично сработано. –

+0

Когда я на самом деле запускаю этот запрос по вашим данным образца, я получаю ошибку «-284: подзапрос вернул не одну строку». Более странно то, что когда я запускаю только подзапрос, я получаю сообщение об ошибке «-324: Неоднозначный столбец (manager_id)». Проблема двусмысленного столбца «уходит», когда список выбора для подзапроса включает 'manager_id':' SELECT employee_id, manager_id FROM empl_relation WHERE manager_id NULL START WITH employee_id = 5150 CONNECT BY employee_id = PRIOR manager_id', но это может ' t будет использоваться непосредственно в основном запросе.Тестирование: Informix 12.10.FC6 в Mac OS X 10.11.5. Комментарии? –

+0

Хорошо. Я не совсем уверен, что здесь происходит. 'ВЫБОР EMPLOYEE_ID, manager_id ОТ empl_relation начать с employee_id = (SELECT EMPLOYEE_ID ОТ empl_relation эр ГДЕ er.manager_id IS NULL ПУСК С employee_id = 5150 CONNECT BY employee_id = ПРЕДВАРИТЕЛЬНОГО manager_id) CONNECT BY ПРИОР employee_id = manager_id ORDER BY employee_id; 'Похоже, если я поместил псевдоним для таблицы во внутренний запрос, проблема двусмысленного столбца исчезнет. Опять же, не уверен, что здесь происходит. – user3244615

2

Это объединяет в себе два запроса в один и, кажется, работает:

SELECT employee_id, manager_id FROM empl_relation 
START WITH employee_id = (
        SELECT h.employee_id 
         FROM (SELECT employee_id, manager_id 
           FROM empl_relation 
          START WITH employee_id = 5150 
          CONNECT BY employee_id = PRIOR manager_id 
          ) AS h 
        WHERE h.manager_id IS NULL) 
CONNECT BY PRIOR employee_id = manager_id 
ORDER BY employee_id; 

В основном, это берет ваш запрос, который работает вверх по иерархии и запускает его, а затем фильтрует результат, чтобы получить топ-менеджер (сотрудник без менеджера) и использует это значение как СТАРТ в запросе «иерархический спуск сверху».

5148 
5149 5148 
5150 5149 
5151 5148 
5152 5151 
5154 5148 
5155 5154 

я получаю тот же результат с любым начальным значением: 5148, 5149, 5150, 5151, 5152, 5154, 5155.

+0

Wow !!!! Это сработало отлично! Большое спасибо за вашу помощь!! – user3244615