Sql-Server

通過從初始總和中順序減去每一行的金額來計算每一行的餘額

  • August 25, 2016

我會用一個例子來解釋這個問題。

將選擇並顯示我所做的提款過程並顯示我的存款餘額狀態的查詢。

使用列,Deposit來創建表。TotalAmount``DepositDate

另一個表Withdrawal是用列創建的WithdrawAmountWithdrawDate

因此,我使用 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)——因此,每一行都會從 中減去不斷增加的數量TotalAmountBalance接近於 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.

引用自:https://dba.stackexchange.com/questions/147555