У меня есть такая таблица:
ItemID ItemFormula
100 'ID_3+ID_5'
110 'ID_2+ID_6'
120 'ID_100+ID_110'
130 'ID_120+ID_4'
Это упрощенная версия таблицы формул с почти 1000 записями и до 40 уровнями ссылок (элементы, используемые в других элементах). Задача состоит в том, чтобы разбить формулы на одну ссылку на уровень, где в одном элементе нет других элементов. Например, в приведенной выше таблице для id = 130 у меня должно быть '((ID_3 + ID_5) + (ID_2 + ID_6)) + ID_4'
РЕДАКТИРОВАТЬ: операции не ограничиваются "+", и элементы имеют характер между ними должен быть узнаваемым. Ради простоты я удалил этот символ.
Я могу использовать для этого рекурсивный CTE. но моя проблема в том, что из-за высокого уровня ссылок мой рекурсивный отбор содержит много записей, поэтому для его завершения требуется много времени.
Мой вопрос таков: могу ли я сохранять предыдущую рекурсию только каждый раз, когда рекурсия бывает?
Вот мой код CTE
WITH Formula
AS (SELECT A.ItemID
,'ID_' + CONVERT(VARCHAR(20), A.ItemID) AS ItemText
,CONVERT(VARCHAR(MAX), A.ItemFormula) AS ItemFormula
FROM (VALUES (100,'ID_3+ID_5'),
(110,'ID_2+ID_6'),
(120,'ID_100+ID_110'),
(130,'ID_120+ID_4')
) A (ItemID,ItemFormula)
)
,REC
AS
(
SELECT A.ItemID
,A.ItemText
,A.ItemFormula
,1 AS LevelID
FROM Formula A
UNION ALL
SELECT A.ItemID
,A.ItemText
,' '
+ TRIM (REPLACE (REPLACE (A.ItemFormula, B.ItemText, ' ( ' + B.ItemFormula + ' ) '), ' ', ' '))
+ ' ' AS ItemFormula
,A.LevelID + 1 AS LevelID
FROM REC A
CROSS APPLY
(
SELECT *
FROM
(
SELECT *
,ROW_NUMBER () OVER (ORDER BY GETDATE ()) AS RowNum
FROM Formula B2
WHERE CHARINDEX (B2.ItemText, A.ItemFormula) > 0
) B3
WHERE B3.RowNum = 1
) B
)
,FinalQ
AS
(
SELECT A2.ItemID
,A2.ItemFormula
,A2.LevelID
FROM
(
SELECT A.ItemID
,REPLACE (TRIM (A.ItemFormula), ' ', '') AS ItemFormula
,A.LevelID
,ROW_NUMBER () OVER (PARTITION BY A.ItemID ORDER BY A.LevelID DESC) AS RowNum
FROM REC A
) A2
WHERE A2.RowNum = 1
)
SELECT * FROM FinalQ A2 ORDER BY A2.ItemID;
Заранее спасибо.