Как самостоятельно присоединиться рекурсивно в SQL? - PullRequest
13 голосов
/ 12 августа 2010

У меня есть таблица:

Series
========
ID
SeriesName
ParentSeriesID

Ряд может быть «корневым», (ParentSeriesID равен 0 или нуль) или может иметь родительский элемент.Ряд также может быть на несколько уровней ниже, то есть у его Родителя есть Родитель, у которого есть Родитель и т. Д.

Как я могу запросить таблицу, чтобы получить Серию по ее ID и ВСЕМ потомкам Серии '?

Пока что я пробовал:

 SELECT child.*
 FROM Series parent JOIN Series child ON child.ParentSeriesID = parent.ID
 WHERE parent.ID = @ParentID

Но это возвращает только первый уровень дочерних элементов, я хочу родительский узел и все "нисходящие" узлы.Я не уверен, как прогрессировать отсюда.

Ответы [ 3 ]

14 голосов
/ 12 августа 2010

Если вы используете SQL Server 2005+, вы можете использовать выражения общей таблицы

With Family As 
( 
Select s.ID, s.ParentSeriesId, 0 as Depth
From Series s
Where ID = @ParentID 
Union All 
Select s2.ID, s2.ParentSeriesId, Depth + 1
From Series s2
    Join Family 
        On Family.ID = s2.ParentSeriesId 
) 
Select *
From Family 

Для получения дополнительной информации:

Рекурсивные запросы с использованием выражений общих таблиц

5 голосов
/ 10 апреля 2013

Я просто усиливаю работу Томаса.Если вам нужно узнать глубину иерархии и получить парентид, вот код.

Это было почти то же самое с работой Томаса.

With Family As 
( 
    Select s.ID, s.ParentSeriesId, 0 as Depth
    From Series s
    Where ID = @ParentID <--- this was removed if you intend to get all hierarchy of the record. You can retain this if you want
  Union All 
     Select s2.ID, s2.ParentSeriesId < --- change to **Family.ParentID**, Depth + 1
     From Series s2
     Join Family 
         On Family.ID = s2.ParentSeriesId 
) 
 Select *
 From Family 

Это все.Я знаю, что уже слишком поздно, но я надеюсь, что любой, кто столкнется с этим, может помочь им.Спасибо Томасу за оригинальный код.:)

2 голосов
/ 12 августа 2010

Используйте функцию CTE, доступную в slq server 2005 и далее, для запроса повторного запроса

USE AdventureWorks
GO
WITH Emp_CTE AS (
SELECT EmployeeID, ContactID, LoginID, ManagerID, Title, BirthDate
FROM HumanResources.Employee
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID, e.ContactID, e.LoginID, e.ManagerID, e.Title, e.BirthDate
FROM HumanResources.Employee e
INNER JOIN Emp_CTE ecte ON ecte.EmployeeID = e.ManagerID
)
SELECT *
FROM Emp_CTE
GO

Пример можно посмотреть здесь:

SQL SERVER - Простой примерРекурсивный CTE

...