#sql #tsql #sql-server-2008
#sql #tsql #sql-server-2008
Вопрос:
На основе самого высокого уровня и для соответствующей записи дочернего идентификатора, т.Е. 71 здесь, мне нужно подняться на уровень до 1 и получить соответствующую запись дочернего идентификатора, т.е. 209
Например:
Чтобы найти дочернюю запись для 71:
родительский уровень 4 — 154, родительский уровень 3 — 192, родительский уровень 2 — 209 или дочерний уровень 1 — 209
209 — необходимый ответ.
Теперь сложная часть заключается в том, что самый высокий уровень является переменным. Мой запрос, показанный выше, не работает, поскольку уровень увеличивается до 6 или 7, поскольку я не буду знать количество необходимых соединений.
Можем ли мы легко сделать это в рекурсивном CTE?
declare @t table (
childID int,
ParentID int,
level int
)
insert into @t
select 71, 154, 4
union
select 154, 192, 3
union
select 192, 209, 2
union
select 209, 0, 1
select * from @t
select t1.childID, t4.ChildID
from @t t1
inner join
@t t2
on t1.ParentID = t2.childID
inner join
@t t3
on t2.ParentID = t3.childID
inner join
@t t4
on t3.ParentID = t4.childID
and t1.childID = 71
-- I tried to with recursive CTE
-- I need to get 71, 209 but getting 209, 0
;with MyCTE as
(
select childID, ParentID from @t t1
where t1.level = 1
UNION ALL
select m.childID, t2.childID from @t t2
inner join
MyCTE m
on m.childID = t2.ParentID
)
select top 1 * from MyCTE
Ответ №1:
Попробуйте это:
declare @t table (
childID int,
ParentID int,
level int
)
insert into @t
select 71, 154, 4
union
select 154, 192, 3
union
select 192, 209, 2
union
select 209, 0, 1
Declare @SearchChild int
set @SearchChild=71
;with MyCTE as (
select t1.childID, t1.ParentID , @SearchChild AS searchChild, t1.level
from @t t1
where t1.childID = @SearchChild
UNION ALL
select t1.childID, t1.ParentID , c.SearchChild, t1.level
from @t t1
inner join MyCTE c on t1.childID=c.ParentID
)
select top 1 * from MyCTE order by level asc
ВЫВОД:
childID ParentID searchChild level
----------- ----------- ----------- -----------
209 0 71 1
Я не уверен, что вам нужно, нет строки, в которой 209 и 71 вместе? это лучшее, что вы можете сделать. Кроме того, этот CTE работает вверх по цепочке, а не вниз, и должен работать намного лучше на больших таблицах.
Ответ №2:
Это способ сделать это:
;with MyCTE as
(
select childID, ParentID, t1.childID As firstChild, 0 As depth
from @t t1
where t1.level = 1
UNION ALL
select t2.childID, t2.ParentID, m.firstChild, m.depth 1
from @t t2
inner join MyCTE m
on m.childID = t2.ParentID
)
select TOP 1 childID, firstChild
from MyCTE
ORDER BY depth DESC
Дает вам
childId firstChild
71 209
Комментарии:
1. не будет работать, если в таблице более одной цепочки, что, я думаю, наиболее вероятно.
2. @KM. Похоже, что он настроен как связанный список
3. тестовые данные представляют собой единую цепочку, но я буду фактическими данными таблицы, содержащими много. Начиная с уровня 1, вам нужно будет обработать все цепочки, чтобы найти
71
дочернюю запись. Однако, если вы начнете с71
дочернего элемента и вернетесь к первому уровню, как я делаю в своем ответе, вы найдете его быстрее, и несколько цепочек не повлияют на результат.