Как перемещаться по дереву/работать с иерархическими данными в коде SQL
Скажем, у меня есть таблица сотрудников с записью для каждого сотрудника в моей компании и столбец для супервизора (как показано ниже). Я хотел бы подготовить отчет, в котором перечислены имена и названия для каждого шага в контрольной строке. например, для dick robbins, 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 внешних объединений... Я надеялся, что есть что-то лучше, чем это, и менее привлекателен, чем курсоры.
Спасибо за любую помощь.
Ответы
Ответ 1
Это, по сути, порт принятого ответа на мой вопрос, который я связал с комментариями OP.
вы можете использовать выражения common-table
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
Для большего:
Рекурсивные запросы с использованием общих выражений таблицы
Ответ 2
Некоторая рекурсивная функция, которая возвращает супервизора (если есть) или null. Может быть SP, который вызывает себя также, и используя UNION.
Ответ 3
Возможно, вас заинтересует решение "Материализованный путь", которое немного де-нормализует таблицу, но может быть использовано для любого типа базы данных SQL и мешает вам выполнять рекурсивные запросы. Фактически, его можно даже использовать для баз данных без SQL.
Вам просто нужно добавить столбец, который содержит всю родословную объекта. Например, в таблице ниже tree_path
столбец с именем 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- '' не может.