- •Урок 12. РекурсивныйSql
- •Древовидные структуры
- •Стандартное представление и манипулирование деревьями в sql
- •Рекурсивные запросы в Oracle
- •Фраза startwith
- •Фраза connectby
- •Использование псевдостолбца level
- •Задание условия
- •Условие на глубину иерархической структуры
- •Упорядочение строк с помощью фразы order by
- •Подзапрос в startwith
- •Рекурсивные запросы в стандарте sql
- •Определение повторяющихся подзапросов
- •Рекурсивное выполнение запросов
- •Примеры рекурсивных запросов: рейсовые полеты
- •Рекурсия с накоплением
- •Рекурсия и соединение таблиц
- •Отрицание и группирование в рекурсии
- •Примеры рекурсивных запросов: комплектация изделий
- •Вычисление промежуточных количественных характеристик
- •Итоговые количественные вычисления
- •Игнорирование фиктивных изделий
- •В каких агрегатах используется деталь?
- •Parts explosion excluding base parts (Testing For Leaf Nodes In a Parts Explosion)
- •Характеристики поиска
- •Фиксация наличия циклов
- •Направление поиска
- •Более сложная структура рекурсивного запроса
- •Рекурсивные представления
- •Различные виды рекурсии
- •Прямая и взаимная рекурсия
- •Линейная и нелинейная рекурсия
- •Подведение итогов
- •Самостоятельная работа
Стандартное представление и манипулирование деревьями в sql
В SQL, любые связи явно описываются данными. Типичный способ представления деревьев состоит в том, чтобы поместить дуги между вершинами в таблицу. Т.е. один столбец — родительский узел, и другой столбец в той же самой строке — дочерний узел (пара представляет собой дугу в графе). Например, в нашей учебной базе данных таблица TEACHERпомимо первичного ключаTchPK, который уникально идентифицирует строки таблицы (то есть преподавателей) имеется внешний ключChief, который является ссылкой на руководителя данного преподавателя.
Чтобы по каждому руководителю получить имена их непосредственных подчиненных, следует использовать «самосоединяющийся» запрос типа:
SELECT mgr.Name AS "Руководитель", tch.Name AS "Подчиненный" FROM TEACHER tch, TEACHER mgr WHERE tch.Chief = mgr.TchPK ORDER BY mgr.Name;
Руководитель Подчиненный --------------- ------------ Заплатинский Козлитин Кузнецов Марченко Лебедь Недоводеев Радишевский Хоменко Радишевский Воробьев Радишевский Кузнецов Сидоров Радишевский Сидоров Заплатинский Сидоров Лебедь Сидоров Резник Хоменко Витковский
11 строк выбрано.
Этот запрос выдает только непосредственных подчиненных. Однако, подчиненные ваших подчиненных также «подвластны» вам, и так далее вниз по дереву. Чтобы вывести сведения по вершинам через уровень в дереве, необходимо написать более сложный запрос с троекратным объединением отношения, как это продемонстрировано ниже.
SELECT mgr.Name AS "Руководитель", tch.Name AS "Подчиненный 2 ур-ня" FROM TEACHER tch, TEACHER mid, TEACHER mgr WHERE tch.Chief = mid.TchPK AND mid.Chief = mgr.TchPK ORDER BY mgr.Name;
Руководитель Подчиненный 2 ур-ня --------------- ------------------- Радишевский Витковский Радишевский Марченко Сидоров Хоменко Сидоров Воробьев Сидоров Недоводеев Сидоров Кузнецов Сидоров Козлитин
7 строк выбрано.
К сожалению, вы понятия не имеете насколько глубоко дерево, так что для получения полной структуры подчинения необходимо продолжать расширять этот запрос аналогичным образом, пока не получите в результате пустое множество. Понятно, такое решение по нахождению дочерних вершин любого уровня в древовидной структуре не является удовлетворительным.
Тем не менее, некоторые из элементов дерева могут эффективно отыскиваться. Так, например, можно легко находить вершины–листья, то есть такие, которые не имеют потомков. В нашем случае это преподаватели, не имеющие подчиненных. Вот как они находятся:
SELECT t1.Name AS "Вершины-листья" FROM TEACHER t1 WHERE NOT EXISTS (SELECT * FROM TEACHER t2 WHERE t2.Chief = t1.TchPK);
Вершины-листья ---------------- Витковский Воробьев Козлитин Марченко Резник Недоводеев Ахромеев Наумов Дараганов
9 строк выбрано.
А как найти корень дерева, то есть «самого высокого» начальника? Ответ на этот запрос зависит от того, какое значение столбца Chiefхранится для корня дерева, то есть для того сотрудника, у которого нет руководителя. Возможны два варианта: хранить в этом столбце значение столбцаTchPK(что, как мы увидим далее, не самый лучший вариант), то есть тем самым указать, что этот сотрудник является сам своим руководителем, и второй — хранить в этом поле значениеNULL. В первом случае для получения корня дерева следует записать:
SELECTNameFROMTEACHERWHERETchPK=Chief;
А во втором:
SELECT Name FROM TEACHER WHERE Chief IS NULL;
Итак, можно констатировать, что теми средствами SQL, которые мы до сих пор изучили, не возможно выразить запросы, производящие поиск и вычисления в деревьях на произвольную глубину вложенности.