Как выполнить рекурсивное объединение, чтобы получить самый низкий уровень данных с помощью TSQL

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

У меня есть следующий набор данных:

 ID          ParentID 
----------- ---------
8320        NULL     
8321        8320     
8322        8320     
8323        8322     
8325        NULL     
8328        8325     
8329        8328 
  

Чего я пытаюсь добиться, так это выбрать все строки, которые принадлежат определенному идентификатору. Например, если я запрашиваю ID = 8320, должны быть возвращены следующие данные:

 ID          ParentID 
----------- ---------
8320        NULL     
8321        8320     
8322        8320     
8323        8322
  

До сих пор это то, что я пытался без реального успеха.

 select *
from JobQueueLog JQL
    left join JobQueueLog JQLC on
        JQL.ID = JQLC.ParentID
    and JQLC.ParentID is not null
where JQL.ID = 8320
  

Любая помощь, пожалуйста?

Ответ №1:

Вам нужно использовать CTE и выполнить рекурсивный запрос

 with tmp (id, parentid) as (
select id, parentid
from rec
where id = 8320
union all
select rec.id, rec.parentid
from tmp
inner join rec on tmp.id = rec.parentid
)
select id, parentid
from tmp
  

Комментарии:

1. @RudolfLamprecht — Вы можете проверить это, изменив представление на Oldest from Votes . Но, во всяком случае, он ответил за несколько секунд до меня, я думаю. Для дифференциации я добавил образец данных .. своего рода демонстрация

2. И большое спасибо за хорошо структурированную и подробную демонстрацию. Ta!

Ответ №2:

Recursive CTE's предназначены для этого

 WITH data
     AS (SELECT *
         FROM   ( VALUES ('8320',NULL),
                         ('8321','8320'),
                         ('8322','8320'),
                         ('8323','8322'),
                         ('8325',NULL),
                         ('8328','8325'),
                         ('8329','8328')) tc ([ID], [ParentID])),
     rec_cte
     AS (SELECT [ID],
                [ParentID]
         FROM   data
         WHERE  [ID] = '8320'
         UNION ALL
         SELECT r.[ID],
                r.[ParentID]
         FROM   rec_cte rc
                JOIN data r
                  ON r.[ParentID] = rc.ID)
SELECT [ID],
       [ParentID]
FROM   rec_cte 
  

Результат :

 ╔══════╦══════════╗
║  ID  ║ ParentID ║
╠══════╬══════════╣
║ 8320NULL     ║
║ 83218320     ║
║ 83228320     ║
║ 83238322     ║
╚══════╩══════════╝
  

Ответ №3:

 ;with cte
as
(
select  * from #temp where id=8320
union all
select t.* from 
cte c 
join 
#temp t on c.id=t.parentid
)
select * from cte