На SQL-Server 2008 вы можете использовать следующее решение:
DECLARE @TBL TABLE(id int, amount int);
INSERT INTO @TBL VALUES
(1, 100), (2, 100), (3, 60), (4, 200), (5, 100);
SELECT t1.ID, t1.amount, SUM(t2.amount) as CumTotal
FROM @TBL t1
CROSS APPLY (SELECT *
FROM @TBL
WHERE ID <= t1.id) t2
GROUP BY t1.ID, t1.amount
HAVING SUM(t1.amount) < 300
ORDER BY t1.ID
;
Вот результат:
ID | amount | CumTotal
-: | -----: | -------:
1 | 100 | 100
2 | 100 | 200
3 | 60 | 260
dbfiddle здесь
Хотя это решение работает хорошо, оно не рекомендуется с точки зрения производительности.
В этом случае лучше всего использовать КУРСОР.
DECLARE @CS table (id int, amount int, total int);
DECLARE @id int, @amount int;
DECLARE @CumSum int = 0;
DECLARE c CURSOR
LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR SELECT ID, amount
FROM @TBL
ORDER BY [id];
OPEN c;
FETCH NEXT FROM c INTO @id, @amount
WHILE @@FETCH_STATUS = 0 AND @CumSum + @amount < 300
BEGIN
SET @CumSum = @CumSum + @amount;
INSERT @CS (id, amount, total)
SELECT @id, @amount, @CumSum;
FETCH NEXT FROM c INTO @id, @amount
END
CLOSE c;
DEALLOCATE c;
SELECT id, amount, total
FROM @CS
ORDER BY id;
GO
id | amount | total
-: | -----: | ----:
1 | 100 | 100
2 | 100 | 200
3 | 60 | 260
dbfiddle здесь
Следующий ответ можно использовать в SQL-SERVER 2012 и более поздних версиях
Вы можете использовать кумулятивную сумму, используя функцию WINDOW и SUM() ROWS UNBOUNDED PRECEDING.
Просмотрите документы MS.
DECLARE @TBL TABLE(id int, amount int);
INSERT INTO @TBL VALUES
(1, 100), (2, 100), (3, 60), (4, 200), (5, 100);
Следующий запрос возвращает совокупную сумму:
SELECT ID,
SUM(amount) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING) AS CumTotal
FROM @TBL
;
ID | CumTotal
-: | -------:
1 | 100
2 | 200
3 | 260
4 | 460
5 | 560
Проблема в том, что вы не можете остановить его, вам нужно вычислить все записи, а затем вы можете применить предложение where только для фильтрации записей.
WITH CSum As
(
SELECT ID,
SUM(amount) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING) AS CumTotal
FROM @TBL
)
SELECT ID, CumTotal
FROM CSum
WHERE CumTotal < 300
ORDER BY ID
;
Это окончательный результат:
ID | CumTotal
-: | -------:
1 | 100
2 | 200
3 | 260
dbfiddle здесь
person
McNets
schedule
21.03.2017