Всем привет!
Есть таблица с данными, нужно построить рекурсивный запрос, который будет эти данные выбирать, как дерево. Проблема в том, что дочерний элемент может ссылаться сам на себя, что приводит к бесконечной рекурсии.
Пример
declare @t table(eNum FLOAT, dNum NVARCHAR(10), tNum FLOAT)
insert into @t values
(1.1, '1.1.1',1.2),
(1.2, '1.2.1',2.1),
(1.3, '1.3.3',(null)),
(1.3, '1.3.12',(NULL)),
(1.3, '1.3.11',(null)),
(1.3, '1.3.15',(null)),
(1.3, '1.3.8',(null)),
(1.3, '1.3.2',(null)),
(1.3, '1.3.13',(null)),
(1.3, '1.3.14',(null)),
(1.3, '1.3.7',(null)),
(1.3, '1.3.9',(null)),
(1.3, '1.3.5',(null)),
(1.3, '1.3.6',(null)),
(1.3, '1.3.10',(null)),
(1.3, '1.3.1',(null)),
(1.3, '1.3.4',(null)),
(2.1, '2.1.4',2.2),
(2.1, '2.1.3',2.2),
(2.1, '2.1.1',2.2),
(2.1, '2.1.6',2.2),
(2.1, '2.1.2',2.2),
(2.1, '2.1.7',2.2),
(2.1, '2.1.5',2.1); --если убрать эту строку, то всё работает
WITH allSteps AS (
SELECT * FROM @t --тут запрос на получение данных из нескольких таблиц
),
AlgoSteps AS (
SELECT alst.eNum, alst.dNum, alst.tNum, 1 AS level
FROM allSteps AS alst
WHERE alst.eNum = 1.1
UNION ALL
SELECT alst.eNum, alst.dNum, alst.tNum, als.level + 1
FROM allSteps AS alst
INNER JOIN AlgoSteps AS als ON alst.eNum = als.tNum
WHERE alst.eNum <> 1.1
)
SELECT * FROM AlgoSteps ORDER BY eNum, dNum
OPTION (MAXRECURSION 5);
Каким образом можно проверить, что элемент уже есть в выборке и проигнорировать его? Пробовал
WHERE alst.eNum <> 1.1 AND NOT EXISTS (SELECT 1 FROM AlgoSteps s WHERE s.eNum = alst.eNum)
но получил ошибку:
Рекурсивный элемент обобщенного табличного выражения "AlgoSteps" имеет множественные рекурсивные ссылки.