Вот пример дерева:
--recursive CTE tree example
DECLARE @Contacts table (id int, first_name varchar(10), reports_to_id int)
INSERT @Contacts VALUES (1,'Jerome', NULL ) -- tree is as follows:
INSERT @Contacts VALUES (2,'Joe' ,'1') -- 1-Jerome
INSERT @Contacts VALUES (3,'Paul' ,'2') -- / \
INSERT @Contacts VALUES (4,'Jack' ,'3') -- 2-Joe 9-Bill
INSERT @Contacts VALUES (5,'Daniel','3') -- / \ \
INSERT @Contacts VALUES (6,'David' ,'2') -- 3-Paul 6-David 10-Sam
INSERT @Contacts VALUES (7,'Ian' ,'6') -- / \ / \
INSERT @Contacts VALUES (8,'Helen' ,'6') -- 4-Jack 5-Daniel 7-Ian 8-Helen
INSERT @Contacts VALUES (9,'Bill ' ,'1') --
INSERT @Contacts VALUES (10,'Sam' ,'9') --
DECLARE @Root_id int
--get complete tree---------------------------------------------------
SET @Root_id=null
PRINT '@Root_id='+COALESCE(''''+CONVERT(varchar(5),@Root_id)+'''','null')
;WITH StaffTree AS
(
SELECT
c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
FROM @Contacts c
LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id
WHERE c.id=@Root_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL)
UNION ALL
SELECT
s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
FROM StaffTree t
INNER JOIN @Contacts s ON t.id=s.reports_to_id
WHERE s.reports_to_id=@Root_id OR @Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree ORDER BY LevelOf,first_name
--get 2 and all below---------------------------------------------------
SET @Root_id=2
PRINT '@Root_id='+COALESCE(''''+CONVERT(varchar(5),@Root_id)+'''','null')
;WITH StaffTree AS
(
SELECT
c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
FROM @Contacts c
LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id
WHERE c.id=@Root_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL)
UNION ALL
SELECT
s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
FROM StaffTree t
INNER JOIN @Contacts s ON t.id=s.reports_to_id
WHERE s.reports_to_id=@Root_id OR @Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree ORDER BY LevelOf,first_name
--get 6 and all below---------------------------------------------------
SET @Root_id=6
PRINT '@Root_id='+COALESCE(''''+CONVERT(varchar(5),@Root_id)+'''','null')
;WITH StaffTree AS
(
SELECT
c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
FROM @Contacts c
LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id
WHERE c.id=@Root_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL)
UNION ALL
SELECT
s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
FROM StaffTree t
INNER JOIN @Contacts s ON t.id=s.reports_to_id
WHERE s.reports_to_id=@Root_id OR @Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree ORDER BY LevelOf,first_name
ВЫХОД:
@Root_id=null
id first_name reports_to_id Manager_id Manager_first_name LevelOf
----------- ---------- ------------- ----------- ------------------ -----------
1 Jerome NULL NULL NULL 1
9 Bill 1 1 Jerome 2
2 Joe 1 1 Jerome 2
6 David 2 2 Joe 3
3 Paul 2 2 Joe 3
10 Sam 9 9 Bill 3
5 Daniel 3 3 Paul 4
8 Helen 6 6 David 4
7 Ian 6 6 David 4
4 Jack 3 3 Paul 4
(10 row(s) affected)
@Root_id='2'
id first_name reports_to_id Manager_id Manager_first_name LevelOf
----------- ---------- ------------- ----------- ------------------ -----------
2 Joe 1 1 Jerome 1
6 David 2 2 Joe 2
3 Paul 2 2 Joe 2
5 Daniel 3 3 Paul 3
8 Helen 6 6 David 3
7 Ian 6 6 David 3
4 Jack 3 3 Paul 3
(7 row(s) affected)
@Root_id='6'
id first_name reports_to_id Manager_id Manager_first_name LevelOf
----------- ---------- ------------- ----------- ------------------ -----------
6 David 2 2 Joe 1
8 Helen 6 6 David 2
7 Ian 6 6 David 2
(3 row(s) affected)