Как выбрать верхний уровень иерархических отношений в SQL? - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть список подпрограмм, которые необходимо запустить, и таблица, которая определяет, зависит ли подпрограмма от успешного завершения других подпрограмм или нет.Так, например:

| RoutineID | DependentRoutineID |
| --------- | ------------------ |
|     1     |         NULL       |
|     2     |          1         |
|     3     |          2         |
|     4     |          3         |
|     5     |          3         |
|     6     |          4         |
|     7     |          5         |
|     8     |         NULL       |
|     9     |          8         |
|     10    |          9         |

Из-за иерархической природы зависимостей все процедуры> = 2 и <= 7 находятся на самом высоком уровне в зависимости от процедуры 1. Я хочу отразить это в запросеэто возвращает "самый высокий" DependentRoutineID для каждого RoutineID </p>

| RoutineID | DependentRoutineID |
| --------- | ------------------ |
|     1     |         NULL       |
|     2     |          1         |
|     3     |          1         |
|     4     |          1         |
|     5     |          1         |
|     6     |          1         |
|     7     |          1         |
|     8     |         NULL       |
|     9     |          8         |
|     10    |          8         |

Я пытался сделать это с помощью рекурсивного CTE, но это не работает, как я ожидал;как я могу выполнить этот запрос?

1 Ответ

2 голосов
/ 25 сентября 2019

Попробуйте это ниже. Рекурсивный CTE

DECLARE @TABLE AS TABLE (RoutineID  INT, DependentRoutineID INT)
INSERT INTO @TABLE 
SELECT  1 , NULL   UNION ALL    
SELECT  2 ,  1     UNION ALL    
SELECT  3 ,  2     UNION ALL    
SELECT  4 ,  3     UNION ALL    
SELECT  5 ,  3     UNION ALL    
SELECT  6 ,  4     UNION ALL    
SELECT  7 ,  5     UNION ALL    
SELECT  8 , NULL   UNION ALL    
SELECT  9 ,  8     UNION ALL    
SELECT  10,  9      

;WITH CTE
AS
(
SELECT RoutineID,
       DependentRoutineID AS DependentRoutineIDDup,
       RoutineID  As DependentRoutineID1         
FROM @TABLE
WHERE DependentRoutineID IS NULL
UNION ALL
SELECT t.RoutineID,
       t.DependentRoutineID,
       DependentRoutineID1       
FROM CTE c
INNER JOIN  @TABLE t
ON c.RoutineID = t.DependentRoutineID
)
SELECT RoutineID, 
       CASE WHEN  DependentRoutineIDDup IS NULL THEN NULL ELSE DependentRoutineID1 END DependentRoutineID
FROM CTE
ORDER BY RoutineID

Результат

RoutineID   DependentRoutineID
------------------------------
1               NULL
2               1
3               1
4               1
5               1
6               1
7               1
8               NULL
9               8
10              8
...