Я думаю, что у меня достаточно хорошо отформатирован формат Рекурсивных CTE, чтобы написать его, но я все равно разочарован тем, что не могу обработать его вручную (притворяюсь, что сам являюсь движком SQL и достигаю набора результатов с помощью ручки и бумага). Я нашел это , которое близко к тому, что я ищу, но недостаточно подробное. У меня нет проблем с отслеживанием рекурсивной функции C ++ и пониманием того, как она работает, но для SQL я не понимаю, почему или как движок знает, что нужно останавливаться. Вызывается ли привязка и рекурсивный блок каждый раз, или привязка пропускается в последующих итерациях? (Я сомневаюсь в этом, но я пытаюсь выразить свое замешательство по поводу того, как он, кажется, прыгает.) Если якорь вызывается каждый раз, как якорь не появляется несколько раз в конечном результате? Я надеюсь, что кто-то может просто разбить строку 1, строку 2 и т. Д. Что происходит и что находится «в памяти» по мере накопления набора результатов.
Я взял на себя смелость украсть мой пример с этой страницы , так как он кажется самым простым для понимания.
DECLARE @tbl TABLE (
Id INT
, [Name] VARCHAR(20)
, ParentId INT
)
INSERT INTO @tbl( Id, Name, ParentId )
VALUES
(1, 'Europe', NULL)
,(2, 'Asia', NULL)
,(3, 'Germany', 1)
,(4, 'UK', 1)
,(5, 'China', 2)
,(6, 'India', 2)
,(7, 'Scotland', 4)
,(8, 'Edinburgh', 7)
,(9, 'Leith', 8)
;
WITH abcd
AS (
-- anchor
SELECT id, Name, ParentID,
CAST(Name AS VARCHAR(1000)) AS Path
FROM @tbl
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.Name, t.ParentID,
CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) AS "Path"
FROM @tbl AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT * FROM abcd