銀行帳戶、庫存管理、資金流向分析等場景,都需要根據時間序列計算「截至當前行的累計值」。典型做法是在同一欄位以正負數區分收入/支出,透過跑總 獲取每筆交易後的即時餘額。
CREATE TABLE [dbo].[BankAccount] (
[TransactionID] [int] IDENTITY(1,1) NOT NULL,
[TransactionDateTime] [datetime] NOT NULL CONSTRAINT [DF_BankAccount_TransactionDateTime] DEFAULT (GETDATE()),
[Amount] [money] NOT NULL CONSTRAINT [DF_BankAccount_Amount] DEFAULT (0),
[TransactionType] [char](1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -- 'C'存入 / 'D'提領
[AccountNumber] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_BankAccount] PRIMARY KEY CLUSTERED ([TransactionID] ASC)
) ON [PRIMARY]
| 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 AS D1
WHERE D1.TransactionDateTime <= D0.TransactionDateTime) AS Balance
FROM dbo.BankAccount AS D0
ORDER BY D0.TransactionDateTime;
| ID | 時間 | 金額 | 餘額 |
|---|---|---|---|
| 1 | 2006-11-03 02:33:42.340 | 10000.00 | 10000.00 |
| 2 | 2006-11-03 02:34:50.467 | -500.00 | 9500.00 |
| 3 | 2006-11-03 02:35:04.857 | 250.00 | 9750.00 |
| 4 | 2006-11-03 02:42:19.763 | -124.25 | 9625.75 |
新增 AccountNumber 欄位,並在子查詢加入分區條件:
SELECT
D0.AccountNumber,
D0.TransactionID,
D0.TransactionDateTime,
D0.Amount,
(SELECT SUM(D1.Amount)
FROM dbo.BankAccount AS D1
WHERE D1.AccountNumber = D0.AccountNumber
AND D1.TransactionDateTime <= D0.TransactionDateTime) AS Balance
FROM dbo.BankAccount AS D0
WHERE D0.AccountNumber = 'A123456'
ORDER BY D0.TransactionDateTime;
初始庫存 1000,依序扣減出貨量:
SELECT
ItemID,
OutQty,
1000 - (SELECT SUM(D1.OutQty)
FROM InventoryLog AS D1
WHERE D1.LogDate <= D0.LogDate) AS CurrentStock
FROM InventoryLog AS D0;
SQL Server 2012+ 可使用 SUM() OVER (PARTITION BY AccountNumber ORDER BY TransactionDateTime ROWS UNBOUNDED PRECEDING),執行計畫更優、語法更簡潔,建議優先採用。