Как пройти по дереву / Работа с иерархическими данными в коде SQL - PullRequest
14 голосов
/ 11 июля 2011

Допустим, у меня есть таблица сотрудников с записями для каждого сотрудника в моей компании и столбец для руководителя (как показано ниже).Я хотел бы подготовить отчет, в котором перечислены имена и названия для каждого шага в строке контроля.например, для Дика Роббинса, 1d # 15, я бы хотел список каждого руководителя в его «цепочке команд», вплоть до президента, большой сыр.Я хотел бы избегать использования курсоров, но если это единственный способ сделать это, то это нормально.

id  fname   lname   title   supervisorid
1   big     cheese  president   1
2   jim     william vice president  1
3   sally   carr    vice president  1
4   ryan    allan   senior manager  2
5   mike    miller  manager 4
6   bill    bryan   manager 4
7   cathy   maddy   foreman 5
8   sean    johnson senior mechanic 7
9   andrew  koll    senior mechanic 7 
10  sarah   ryans   mechanic    8
11  dana    bond    mechanic    9
12  chris   mcall   technician  10
13  hannah  ryans   technician  10
14  matthew miller  technician  11
15  dick    robbins technician  11

Реальные данные, вероятно, не будут иметь глубину более 10 уровней ... но яЯ предпочел бы не просто делать 10 внешних соединений ... Я надеялся, что было что-то лучше, и менее вовлечено, чем курсоры.

Спасибо за любую помощь.

Ответы [ 4 ]

20 голосов
/ 11 июля 2011

Это в основном порт принятого ответа на мой вопрос, на который я ссылался в комментариях ОП.

Вы можете использовать общие таблицы

WITH Family As 
( 
    SELECT e.id, e.supervisorid, 0 as Depth
    FROM Employee e
    WHEREid = @SupervisorID 
    UNION All 
    SELECT e2.ID, e2.supervisorid, Depth + 1
    FROM Employee e2
        JOIN Family 
            On Family.id = e2.supervisorid 
) 
SELECT*
FROM Family 

Для более:

Рекурсивные запросы с использованием общих табличных выражений

0 голосов
/ 23 октября 2018

SQL - это язык для выполнения операций set , а рекурсия - , а не одна из них. Кроме того, многие системы баз данных имеют ограничения по рекурсии, использующие хранимые процедуры в качестве меры безопасности, предотвращающей изгнание мошеннического кода ценными ресурсами сервера.

Таким образом, при работе с SQL всегда думайте «плоский» , а не «иерархический». Поэтому я настоятельно рекомендую предложенный метод 'tree_path' . Я использовал тот же подход, и он работает чудесно и очень важно, очень надежно .

0 голосов
/ 03 мая 2014

Возможно, вас заинтересует решение «Materialized Path», которое немного де-нормализует таблицу, но может использоваться в любом типе базы данных SQL и не позволяет выполнять рекурсивные запросы Фактически, его можно использовать даже в базах данных без SQL.

Вам просто нужно добавить столбец, который содержит всю родословную объекта. Например, приведенная ниже таблица содержит столбец с именем tree_path:

+----+-----------+----------+----------+
| id | value     | parent   | tree_path|
+----+-----------+----------+----------+
|  1 | Some Text |        0 |          |
|  2 | Some Text |        0 |          |
|  3 | Some Text |        2 |       -2-|
|  4 | Some Text |        2 |       -2-|
|  5 | Some Text |        3 |     -2-3-|
|  6 | Some Text |        3 |     -2-3-|
|  7 | Some Text |        1 |       -1-|
+----+-----------+----------+----------+

Выбор всех потомков записи с id = 2 выглядит следующим образом:

SELECT * FROM comment_table WHERE tree_path LIKE '-2-%' ORDER BY tree_path ASC

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

Вы также можете индексировать tree_path, и индекс можно использовать, когда подстановочный знак не в начале.

Например, tree_path LIKE '-2-%' может использовать индекс, а tree_path LIKE% - 2-'не может.

0 голосов
/ 11 июля 2011

Некоторая рекурсивная функция, которая возвращает супервизор (если есть) или ноль. Может быть SP, который также вызывает себя и использует UNION.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...