Вернуть узлы самого нижнего уровня (листья) с узлами самого верхнего уровня (корни) - PullRequest
3 голосов
/ 04 июля 2019

Я хотел бы получить все листья и их корни из иерархической таблицы.Лист - это узел самого низкого уровня, а корень - это узел самого верхнего уровня.

При наличии такого дерева, как:

A
--B
  --C
  --D
E
--F
--G
  --H

Листья - это узлы: C, D Корни:A, E

Таблица выглядит следующим образом (для ясности я поставил родительские имена в скобках):

Id | Parent | Name
0  | NULL   | A
1  | 0 (A)  | B
2  | 1 (B)  | C
3  | 1 (B)  | D
4  | NULL   | E
5  | 4 (E)  | F
6  | 4 (E)  | G
7  | 6 (G)  | H

Результат, который я ищу:

Id | Parent | Name
2  | 0 (A)  | C
3  | 0 (A)  | D
5  | 4 (E)  | F
7  | 4 (E)  | H

Я уже настроил следующий запрос CTE, который может найти все корни для каждого листа.

WITH Tree (Id, [Name], Parent) AS
(

      SELECT

            Id, [Name], Parent

      FROM

            dbo.Department

      WHERE 
           --Every leaf node, that is: a node that is never a parent
           Id IN (

            SELECT Id
            FROM Department
            WHERE Id NOT IN (
                SELECT Parent FROM Department
                WHERE Parent IS NOT NULL
            ))


      UNION ALL 

      SELECT

            dept.Id, dept.[Name], dept.Parent

      FROM

            dbo.Department dept

      INNER JOIN Tree ON 

            dept.Id = Tree.Parent

)
SELECT * FROM Tree
WHERE Parent IS NULL

Но я не знаю, как добавить идентификатор листьев в результатвместе с его корнем.

1 Ответ

3 голосов
/ 04 июля 2019

Что-то вроде

WITH cte(id, name, root) AS
  (SELECT id, name, id FROM department WHERE parent IS NULL
   UNION ALL
   SELECT d.id, d.name, root
   FROM department AS d
   JOIN cte AS c ON d.parent = c.id)
SELECT id, root, name
FROM cte AS c
WHERE NOT EXISTS (SELECT 1 FROM department AS d WHERE c.id = d.parent)
ORDER BY id;

даст вам все листья и их корни:

id          root        name      
----------  ----------  ----------
2           0           C         
3           0           D         
5           4           F         
7           4           H         

db <> пример скрипки


Хитрость заключается в том, чтобы столбец в cte начинался с идентификатора каждого корня, который передается без изменений каждому потомку, внуку и т. Д. По очереди.Затем просто отфильтруйте не листовые строки.

...