場景:事件時間序列的累計計算
典型案例:銀行帳戶存/取款記錄,需在每筆交易後即時顯示當前餘額。
資料表結構
CREATE TABLE dbo.BankAccount (
TransactionID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
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
TransactionID,
TransactionDateTime,
Amount,
(SELECT SUM(Amount)
FROM dbo.BankAccount AS D1
WHERE D1.TransactionDateTime <= D0.TransactionDateTime) AS Balance
FROM dbo.BankAccount AS D0
ORDER BY 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 |
擴展應用
- 多帳戶:加入
AccountNumber 欄位與 WHERE AccountNumber = @AcctNo 謂詞
- 庫存試算:初始庫存 1000,後續扣減領料/入庫單,同樣邏輯適用
兩大優勢
- 零儲存開銷:無需物化餘額欄位,主鍵/外鍵索引下查詢極快
- 可追溯稽核:逐筆交易可檢視,異常交易即時定位隔離
效能提示
- 大資料量時考慮改寫為
SUM() OVER (ORDER BY TransactionDateTime ROWS UNBOUNDED PRECEDING)(SQL Server 2012+ 視窗函數)
- 確保
TransactionDateTime 有索引支援範圍掃描