Создание рекурсивного CTE (Common Table Expression)
На этом шаге вы узнаете, как создавать и использовать рекурсивное Common Table Expression (CTE) (общее табличное выражение) в SQLite. Рекурсивные CTE используются для запроса иерархических или древовидных данных. Они позволяют перемещаться по связям внутри таблицы и извлекать данные на разных уровнях иерархии.
Рекурсивный CTE - это CTE, который ссылается сам на себя. Он состоит из двух частей:
- Anchor Member (Якорный элемент): Начальный оператор
SELECT
, который определяет базовый случай или отправную точку рекурсии.
- Recursive Member (Рекурсивный элемент): Оператор
SELECT
, который ссылается на сам CTE. Эта часть выполняет рекурсивный шаг, основываясь на результатах предыдущей итерации.
Якорный и рекурсивный элементы объединяются с помощью оператора UNION ALL
. Рекурсия продолжается до тех пор, пока рекурсивный элемент не вернет пустой набор результатов.
Сначала давайте создадим таблицу с именем employees_hierarchy
(иерархия сотрудников) со следующей структурой:
CREATE TABLE employees_hierarchy (
id INTEGER PRIMARY KEY,
name TEXT,
manager_id INTEGER,
title TEXT
);
Эта таблица представляет иерархию сотрудников, где manager_id
ссылается на id
менеджера сотрудника. Выполните приведенную выше команду в командной строке sqlite>
.
Затем вставьте несколько примеров данных в таблицу employees_hierarchy
:
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Alice', NULL, 'CEO');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Bob', 1, 'VP of Marketing');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Charlie', 1, 'VP of Sales');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('David', 2, 'Marketing Manager');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Eve', 3, 'Sales Manager');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Frank', 4, 'Marketing Specialist');
INSERT INTO employees_hierarchy (name, manager_id, title) VALUES ('Grace', 5, 'Sales Representative');
Здесь Алиса - генеральный директор (нет менеджера), Боб и Чарли подчиняются Алисе, Дэвид подчиняется Бобу, Ева подчиняется Чарли, Фрэнк подчиняется Дэвиду, а Грейс подчиняется Еве. Выполните приведенные выше команды в командной строке sqlite>
.
Теперь давайте создадим рекурсивный CTE для извлечения всей иерархии под Алисой (генеральным директором). Выполните следующий SQL-запрос:
WITH RECURSIVE
EmployeeHierarchy(id, name, manager_id, title, level) AS (
-- Anchor member: Select the CEO
SELECT id, name, manager_id, title, 0 AS level
FROM employees_hierarchy
WHERE manager_id IS NULL
UNION ALL
-- Recursive member: Select employees reporting to the current level
SELECT e.id, e.name, e.manager_id, e.title, eh.level + 1
FROM employees_hierarchy e
JOIN EmployeeHierarchy eh ON e.manager_id = eh.id
)
SELECT id, name, title, level
FROM EmployeeHierarchy;
Этот запрос определяет рекурсивный CTE с именем EmployeeHierarchy
(ИерархияСотрудников). Якорный элемент выбирает генерального директора (где manager_id
равен NULL). Рекурсивный элемент объединяет таблицу employees_hierarchy
с CTE EmployeeHierarchy
, чтобы найти сотрудников, которые подчиняются сотрудникам, выбранным на предыдущем уровне. Столбец level
отслеживает глубину в иерархии.
Ожидаемый результат:
1|Alice|CEO|0
2|Bob|VP of Marketing|1
3|Charlie|VP of Sales|1
4|David|Marketing Manager|2
5|Eve|Sales Manager|2
6|Frank|Marketing Specialist|3
7|Grace|Sales Representative|3
Это показывает всю иерархию сотрудников, где level
указывает уровень подчинения.