Jam*_*YTL 3 sql-server select sql-server-2014 running-totals
我会用一个例子来解释这个问题。
一个查询,将选择并显示我所做的提款流程并显示我的存款余额状态。
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
Run Code Online (Sandbox Code Playgroud)
所以对于这个查询,假设我有 500 的存款,并且只会存款一次。如果我这个月只提现一次,然后把押金全部提现,效果会很好。结果将显示如下:
| WithdrawAmount | Status |
| 500 | ZeroBalanceOops |
Run Code Online (Sandbox Code Playgroud)
但是,如果我在一个月内提款不止一次,并且这些提款将使余额 = 0,则它不起作用。假设存款再次为 500,结果将显示如下:
| WithdrawAmount | Status |
| 250 | StillAvailableYAY |
| 250 | StillAvailableYAY |
Run Code Online (Sandbox Code Playgroud)
预期的结果是在第一次提款时具有“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
;
Run Code Online (Sandbox Code Playgroud)
WHERE 子句应该将表过滤到一个存款行,Deposit
以及从Withdrawal
. 如果表支持多个帐户并且金额需要按帐户进一步关联,您可能需要将 FROM 子句替换为如下内容:
FROM
dbo.Deposit AS d
INNER JOIN dbo.Withdrawal AS w ON d.AccountNumber = w.AccountNumber
Run Code Online (Sandbox Code Playgroud)
该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
;
Run Code Online (Sandbox Code Playgroud)
当然,如果你真的不需要返回余额——只是将它与 0 进行比较,那么不需要嵌套,你可以将d.TotalAmount - SUM(w.WithdrawAmount) OVER (ORDER BY w.WithdrawDate ASC)
表达式直接放入 CASE 中,替换Balance
.