Мне нужно найти в хранимой процедуре, какие значения соответствуют искомому итоговому значению в соответствии с решением valex рекурсивный запрос в SQL Server
Следующее работает довольно хорошо, предполагая, что набор записей привязки CTE очень мал
CREATE TABLE #t ([id] INT, [num] FLOAT);
DECLARE @wanted FLOAT = 100000
INSERT INTO #t ([id], [num])
VALUES (1, 17000), (2, 33000), (3, 53000), (4, 47000), (5, 10000),
(6, 53000), (7, 7000), (8, 10000), (9, 20000), (10, 5000),
(11, 40000), (12, 30000), (13, 10000), (14, 8000), (15, 8000),
(16, 10000), (17, 74000)
/* when you add more records the query becomes too slow, remove this comment
to test*/
/*,(18,10000),(19,78000),(20,10000),(21,10000),(22,80000),(23,19000),
(24,8000),(25,5000),(26,10000),(27,4000),(28,46000),(29,48000),(30,20000),
(31,10000),(32,25000),(33,10000),(34,13000),(35,16000),(36,10000),
(37,5000), 38,5000),(39,30000),(40,15000),(41,10000)*/
;
CREATE NONCLUSTERED INDEX [idx_id] ON #t ([id]);
WITH CTE AS
(
SELECT
id, num AS CSum,
CAST(id AS VARCHAR(MAX)) AS path
FROM
#t
WHERE num <= @wanted
UNION ALL
SELECT
#t.id, #t.num + CTE.CSum AS CSum,
CTE.path + ',' + CAST(#t.id AS VARCHAR(MAX)) AS path
FROM
#T
INNER JOIN
CTE ON #T.num + CTE.CSum <= @wanted AND CTE.id < #T.id
WHERE
#T.num + CTE.CSum <= @wanted
)
SELECT TOP 1 Path
FROM CTE
WHERE CTE.CSum = @wanted
ORDER BY id
DROP TABLE #t
Будет возвращено 3,4, которые являются первыми 2 строками, чьи значения [num] дают итоговое значение @wanted.
Это работает достаточно быстро, когда в записи всего несколько записей.временная таблица #t, но когда вы удаляете комментарий и все оставшиеся записи (от идентификатора 17 до идентификатора 41), запрос выполняется всегда, потому что CTE растет в геометрической прогрессии.
Есть ли способ ускорить код?мне просто нужно первое общее количество (набор данных привязки к списку упорядочен, поэтому результат как 3,4 лучше, чем 8,20,22)