需求:交易明細表含存入 (正) / 提領 (負) 金額,查詢需顯示每筆交易後的「當前餘額」(所有前序交易金額加總)。本文示範使用相關子查詢單查詢完成,無需臨時表或游標,邏輯清晰效能佳。
資料表結構
CREATE TABLE dbo.BankAccount (
TransactionID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
TransactionDateTime DATETIME NOT NULL DEFAULT GETDATE(),
Amount MONEY NOT NULL DEFAULT 0, -- 正=存入, 負=提領
TransactionType CHAR(1) NOT NULL, -- D/C 等
AccountNumber VARCHAR(50) NULL
);
範例資料
| TransactionID | TransactionDateTime | Amount |
| 1 | 2006-11-03 02:33:42.340 | 10000.00 |
| 2 | 2006-11-03 02:34:50.467 | -500.00 |
| 3 | 2006-11-03 02:35:04.857 | 250.00 |
| 4 | 2006-11-03 02:42:19.763 | -124.25 |
核心查詢:相關子查詢計算累計餘額
SELECT
d0.TransactionID,
d0.TransactionDateTime,
d0.Amount,
(SELECT SUM(d1.Amount)
FROM dbo.BankAccount d1
WHERE d1.TransactionDateTime <= d0.TransactionDateTime
AND d1.AccountNumber = d0.AccountNumber -- 多帳戶時必加
) AS Balance
FROM dbo.BankAccount d0
ORDER BY d0.TransactionDateTime;
結果
| ID | 時間 | 金額 | 餘額 |
| 1 | 02:33:42 | 10000.00 | 10000.00 |
| 2 | 02:34:50 | -500.00 | 9500.00 |
| 3 | 02:35:04 | 250.00 | 9750.00 |
| 4 | 02:42:19 | -124.25 | 9625.75 |
兩大優勢
- 零儲存、即時計算:餘額不落地,查詢時即時聚合,帳戶數據量小則閃電快;大量時加上
TransactionDateTime 索引極佳。
- 可稽核、可回溯:每筆交易獨立可驗,異常時可精準定位導致餘額異常的單筆交易,符合金融稽核需求。
擴充應用
- 多帳戶:加
AccountNumber 分組,子查詢加 AND d1.AccountNumber = d0.AccountNumber。
- 存貨餘量:初始庫存 1000,後續出入庫正負相加,同樣邏輯。
- 效能優化:大量資料改用
SUM() OVER (PARTITION BY Account ORDER BY DateTime ROWS UNBOUNDED PRECEDING) (SQL 2012+) 窗口函數,避免逐列子查詢掃描。