Рекурсивная функция parent-child в t-sql - PullRequest
1 голос
/ 19 сентября 2019

У меня есть две таблицы, и я хочу сделать рекурсивный запрос, чтобы получить окончательную таблицу с отношением родитель-потомок и столбец, в котором указано, есть ли у него дочерние элементы.Моя идея состояла в том, чтобы объединить обе таблицы и использовать CTE (запрос выдает ошибку, я прикрепляю его) и изображение того, что я хочу сделать.

ОПИСАНИЕ Таблица 1 и 2покажите нам состояние Учетной записи и Операции, в таблице 1 есть все «Продукт» 999, а в таблице 2 - все «Продукт» 39. Основная идея этого заключается в поиске происхождения Учетной записи и Операции с «Продуктом»999 в таблице 1, например:

В таблице 1,

  • Во-первых, строка с Product_Ini = 999 / Acccount_Ini = 777 / Operation_Ini = 888 получена из Product_Fin = 999 / Acccount_Fin= 777 / Operation_Fin = 666
  • Во-вторых, идея состоит в том, чтобы найти источник Product_Fin = 999 / Acccount_Fin = 777 / Operation_Fin = 666, чтобы сделать это, я делаю CTE в той же таблице ия нахожу Product_Fin = 39 / Acccount_Fin = 126 / Operation_Fin = 333
  • В-третьих, идея состоит в том, чтобы искать происхождение Product_Fin = 39 / Acccount_Fin = 126 / Operation_Fin = 333, чтобы сделать это, у меня естьвиспользуйте таблицу 2 и выполните поиск там, получив результат Product_Fin = 32 / Acccount_Fin = 126 / Operation_Fin = 858
  • Наконец, я хочу получить таблицу, показывающую эволюцию учетной записи, со столбцом Child, который означает, что еслиучетная запись / операция имеет дочерних элементов.

enter image description here enter image description here enter image description here

ЗАПРОС:

drop table #table_1
go
create table #table_1
(
    Product_Ini int,
    Account_Ini int,
    Operation_Ini   int,
    Product_Fin int,
    Account_Fin int,
    Operation_Fin int
)
go

drop table #table_2
go
create table #table_2
(
    Product_Ini int,
    Account_Ini int,
    Operation_Ini   int,
    Product_Fin int,
    Account_Fin int,
    Operation_Fin int
)
go

insert into #table_1 values (999, 123, 456, 32  ,123, 426)
insert into #table_1 values (999, 123, 456, 23  ,123, 159)
insert into #table_1 values (999, 123, 456, 65  ,123, 486)
insert into #table_1 values (999, 596, 162, 32  ,596, 263)
insert into #table_1 values (999, 126, 529, 999 ,126, 459)
insert into #table_1 values (999, 126, 459, 32  ,126, 784)
insert into #table_1 values (999, 126, 741, 999 ,126, 852)
insert into #table_1 values (999, 126, 852, 999 ,126, 111)
insert into #table_1 values (999, 126, 111, 999 ,126, 333)
insert into #table_1 values (999, 126, 333, 32  ,126, 995)
insert into #table_1 values (999, 523, 542, 999 ,523, 478)
insert into #table_1 values (999, 777, 888, 999 ,777, 666)
insert into #table_1 values (999, 777, 666, 39  ,126, 333)
insert into #table_1 values (999, 899, 565, 39  ,899, 474)
insert into #table_1 values (999, 565, 145, 39  ,565, 424)
insert into #table_1 values (999, 565, 361, 85  ,565, 452)
----
insert into #table_2 values (39, 126, 333, 32   ,126, 858)
insert into #table_2 values (39, 899, 474, 999  ,899, 525)
insert into #table_2 values (39, 565, 424, 999  ,565, 361)
--

select * from #table_1
select * from #table_2

;WITH ctetable(depth, Product_Ini, Account_Ini, Operation_Ini, Product_Fin, Account_Fin, Operation_Fin) as 
(
    SELECT 1 as depth, Product_Ini, Account_Ini, Operation_Ini, Product_Fin, Account_Fin, Operation_Fin
    FROM #table_1 as a 
    UNION ALL
    SELECT b.depth + 1 AS depth, b.Product_Ini, b.Account_Ini, b.Operation_Ini, c.Product_Fin, c.Account_Fin, c.Operation_Fin
    FROM ctetable AS b JOIN #table_1 as c on c.Product_Ini = b.Product_Fin and c.Account_Ini = b.Account_Fin and c.Operation_Ini = b.Operation_Fin
)
SELECT * 
--INTO #TMP_FINAL
FROM CTETABLE 
order by Account_Ini, Operation_Ini
GO

СТОЛЫ enter image description here

1 Ответ

1 голос
/ 20 сентября 2019

Я боюсь, что это не может быть строго возможно с рекурсивным CTE.

Давайте пока проигнорируем таблицу 2 и просто посмотрим на простую скобку 4 из вашего примера в светло-зеленом:

enter image description here

Теперь для этого вам необходимо рассмотреть естественный «якорь» (см. Ниже) - строка № 1, оканчивающаяся на 852. Проблема в том, что вы не можете отличить ее естественным образом.из остальных трех, поскольку все они имеют общие характеристики.

Теперь вы можете отличить четвертую строку (заканчивающуюся в 995) от других (используя product_ini <> product_fin), однако на самом деле это неверный конец вашей цепочки CTE, чтобы подняться вверх - якорь должен быть неизменными не может наследовать от остальной части рекурсивного CTE - по самой своей природе он должен быть статическим.

См. прилагаемую разбивку.

enter image description here

Теперь нельзя сказать, что эта проблема не может быть решена, она просто не может быть решена с помощью рекурсивного CTE.

Я бы посоветовал взглянуть на ряд условных самосоединений и описаний дел, а не пытаться быть слишком «умным» здесь.Учитывая, что есть только 3 уровня для прохождения, вы можете довольно просто «жестко закодировать» ряд тестов, и я подозреваю, что это будет лучшим использованием вашего времени.

...