業務場景:給定總可用金額 (如 1700),依訂單編號順序逐筆核銷,餘額不足時該筆部分核銷,後續訂單核銷金額為 0。本文展示使用 CTE (Common Table Expression) 的集合式解法,避免游標/迴圈,效能與可讀性俱佳。
CREATE TABLE #t (id INT, dingdan VARCHAR(20), sale MONEY); INSERT INTO #t VALUES (1,'a',100),(2,'b',200),(3,'c',300),(4,'d',400),(5,'e',500), (6,'f',600),(7,'g',700),(8,'h',800),(9,'i',900),(10,'j',1000);
curr_sale_sum)curr_sale_sum + 當筆金額 ≤ 總額度 → 全額核銷總額度 - curr_sale_sum (剩餘額度);WITH x1 AS (
SELECT
t1.id, t1.dingdan, t1.sale,
(SELECT ISNULL(SUM(t2.sale),0) FROM #t t2 WHERE t2.id < t1.id) AS curr_sale_sum
FROM #t t1
),
x2 AS (
SELECT
id, dingdan, sale,
CASE WHEN curr_sale_sum + sale <= 1700 THEN sale
ELSE 1700 - curr_sale_sum END AS new_sale
FROM x1
)
SELECT
id AS 序號, dingdan AS 訂單, sale AS 訂單金額,
CASE WHEN new_sale < 0 THEN 0 ELSE new_sale END AS 核銷金額
FROM x2;
序號 訂單 訂單金額 核銷金額 1 a 100.00 100.00 2 b 200.00 200.00 3 c 300.00 300.00 4 d 400.00 400.00 5 e 500.00 300.00 -- 餘額 300,部分核銷 6 f 600.00 0.00 -- 餘額耗盡 7 g 700.00 0.00 ...
SELECT
id, dingdan, sale,
CASE
WHEN SUM(sale) OVER (ORDER BY id ROWS UNBOUNDED PRECEDING) <= 1700 THEN sale
WHEN SUM(sale) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) < 1700
THEN 1700 - SUM(sale) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
ELSE 0
END AS 核銷金額
FROM #t;
id 連續無間隙;實務上若有刪除導致間隙,請先用 ROW_NUMBER() OVER (ORDER BY 排序欄位) 產生連續序號再套用邏輯。DECIMAL(19,4) 或 MONEY,避免浮點誤差。