通過從初始總和中順序減去每一行的金額來計算每一行的餘額
我會用一個例子來解釋這個問題。
將選擇並顯示我所做的提款過程並顯示我的存款餘額狀態的查詢。
使用列,
Deposit
來創建表。TotalAmount``DepositDate
另一個表
Withdrawal
是用列創建的WithdrawAmount
,WithdrawDate
。因此,我使用 SELECT 查詢從兩個帶有公式的表中進行選擇:
SELECT WithdrawAmount, CASE WHEN ( TotalAmount - WithdrawAmount) = 0 THEN 'ZeroBalanceOops' ELSE 'StillAvailableYAY' as 'Status' FROM Deposit Inner Join Withdraw WHERE [WithdrawDate] between this month beginning and ending
所以對於這個查詢,假設我有 500 的存款,並且只會存款一次。如果我這個月只提款一次並完全提取存款,效果很好。結果將如下所示:
| WithdrawAmount | Status | | 500 | ZeroBalanceOops |
但是,如果我在一個月內提款超過一次,並且這些提款將使餘額 = 0,則它不起作用。假設存款再次為 500,結果將顯示如下:
| WithdrawAmount | Status | | 250 | StillAvailableYAY | | 250 | StillAvailableYAY |
預期的結果是在第一次提款時出現“StillAvailableYAY”,然後在第二次提款時出現“ZeroBalanceOops”,但由於它只比較,
500-250
因此500-250-250
它將始終是“StillAvailableYAY”狀態。使用SUM(WithdrawalAmount)
不會給出我想要的結果,因為它會導致兩次提款的狀態為“ZeroBalanceOops”。關於如何檢索先前選擇的查詢並將其包含到計算中的任何想法?或者有沒有更好的方法來做到這一點?
這是一個“執行總計”類型的問題:每一行的總數是根據該行的值添加到前一行的總數或從前一行的總數中減去來計算的。
由於您使用的是 SQL Server 2014,因此 Transact-SQL 具有可用的內置語法來幫助您獲得結果。
使用“每月一次存款,每月多次取款”的簡化模型,SQL 語句可以是這樣的:
SELECT d.TotalAmount, w.WithdrawAmount, Balance = d.TotalAmount - SUM(w.WithdrawAmount) OVER (ORDER BY w.WithdrawDate ASC) FROM dbo.Deposit AS d, dbo.Withdrawal AS w WHERE d.DepositDate >= *start_of_this_month* AND d.DepositDate < *start_of_next_month* AND w.WithdrawDate >= *start_of_this_month* AND w.WithdrawDate < *start_of_next_month* ;
WHERE 子句應該將表過濾到一個存款行,
Deposit
以及多少個相應的取款行Withdrawal
。如果表支持多個帳戶並且金額需要按帳戶進一步關聯,您可能希望將 FROM 子句替換為以下內容:FROM dbo.Deposit AS d INNER JOIN dbo.Withdrawal AS w ON d.AccountNumber = w.AccountNumber
該
SUM(w.WithdrawAmount) OVER (ORDER BY w.WithdrawDate ASC)
表達式計算每一行的執行WithdrawAmount
總計。因此,總數隨著每一行而增加(按 的升序排序WithdrawDate
)——因此,每一行都會從 中減去不斷增加的數量TotalAmount
,Balance
接近於 0。上面的查詢會給你每一行的餘額,但不是狀態。要獲取狀態,您需要引用該
Balance
值以將其與 0 進行比較並選擇相應的狀態字元串以返回。Balance
是一個計算列,為了能夠引用它,您需要將上述查詢和引用嵌套Balance
在外層。可以使用派生表或公用表表達式 (CTE) 進行嵌套。此查詢使用 CTE:WITH balances AS ( SELECT d.TotalAmount, w.WithdrawAmount, Balance = d.TotalAmount - SUM(w.WithdrawAmount) OVER (ORDER BY w.WithdrawDate ASC) FROM dbo.Deposit AS d, dbo.Withdrawal AS w WHERE d.DepositDate >= *start_of_this_month* AND d.DepositDate < *start_of_next_month* AND w.WithdrawDate >= *start_of_this_month* AND w.WithdrawDate < *start_of_next_month* ) SELECT TotalAmount, WithdrawAmount, Balance, Status = CASE WHEN Balance > 0 THEN 'StillAvailableYAY' ELSE 'ZeroBalanceOops' END FROM balances ;
當然,如果你真的不需要返回餘額——只需將其與 0 進行比較,則不需要嵌套,你可以將
d.TotalAmount - SUM(w.WithdrawAmount) OVER (ORDER BY w.WithdrawDate ASC)
表達式直接放入 CASE,替換Balance
.