銀行帳戶交易表記錄存款(正數)與提款(負數),需查詢每筆交易後的累計餘額。
CREATE TABLE dbo.BankAccount (
TransactionID INT IDENTITY(1,1) PRIMARY KEY,
TransactionDate DATETIME NOT NULL DEFAULT GETDATE(),
Amount MONEY NOT NULL DEFAULT 0,
TransactionType CHAR(1) NOT NULL, -- 'D' 存款, 'W' 提款
AccountNumber VARCHAR(50) NULL
);
INSERT INTO dbo.BankAccount (TransactionDate, Amount, TransactionType) VALUES
('2006-11-03 02:33:42', 10000.00, 'D'),
('2006-11-03 02:34:50', -500.00, 'W'),
('2006-11-03 02:35:04', 250.00, 'D'),
('2006-11-03 02:42:19', -124.25, 'W');
SELECT
ba.TransactionID,
ba.TransactionDate,
ba.Amount,
(SELECT SUM(Amount) FROM dbo.BankAccount WHERE TransactionID <= ba.TransactionID) AS RunningBalance
FROM dbo.BankAccount ba
ORDER BY ba.TransactionID;
SELECT
TransactionID,
TransactionDate,
Amount,
SUM(Amount) OVER (ORDER BY TransactionID ROWS UNBOUNDED PRECEDING) AS RunningBalance
FROM dbo.BankAccount
ORDER BY TransactionID;
ROWS UNBOUNDED PRECEDING 明確指定框架為「從第一列到目前列」,效能優於預設 RANGE。PARTITION BY AccountNumber 支援多帳戶並行計算。SELECT
a.TransactionID,
a.TransactionDate,
a.Amount,
SUM(b.Amount) AS RunningBalance
FROM dbo.BankAccount a
JOIN dbo.BankAccount b ON b.TransactionID <= a.TransactionID
GROUP BY a.TransactionID, a.TransactionDate, a.Amount
ORDER BY a.TransactionID;
效能較差(O(N²)),僅供教學參考。
| TransactionID | Amount | RunningBalance |
|---|---|---|
| 1 | 10000.00 | 10000.00 |
| 2 | -500.00 | 9500.00 |
| 3 | 250.00 | 9750.00 |
| 4 | -124.25 | 9625.75 |
SELECT
CAST(TransactionDate AS DATE) AS TxnDate,
SUM(Amount) AS DailyNet,
SUM(SUM(Amount)) OVER (ORDER BY CAST(TransactionDate AS DATE) ROWS UNBOUNDED PRECEDING) AS ClosingBalance
FROM dbo.BankAccount
GROUP BY CAST(TransactionDate AS DATE)
ORDER BY TxnDate;
SQL Server 2012+ 請直接使用 SUM() OVER (ORDER BY ... ROWS UNBOUNDED PRECEDING),語法簡潔、效能最佳、支援分區。舊版本可用相關子查詢或臨時表迴圈實現。