SQL窗口函数和运行总计

Posted

技术标签:

【中文标题】SQL窗口函数和运行总计【英文标题】:SQL window function and running total 【发布时间】:2021-07-16 13:35:17 【问题描述】:

我正在学习 SQL,想更好地理解窗口函数。

假设我有一组银行帐户的数据,其中包含:

    最新余额(仅显示最新余额,不显示历史余额) 交易日期 入金金额 提现金额

从这些数据中,我想得到一个列,显示everey 交易中的运行总计(“余额”),如下所示:

account latest_balance date deposit withdrawal balance
XYZ 1 000 2021-07-16 100 1 000
XYZ 1 000 2021-07-15 200 900

由于数据不包含该账户的全部交易历史,并且可用日期是最近 1 年,因此获取“余额”的一种方法是根据最新余额进行计算。我已经尝试为此使用窗口功能。但是我无法让它按照我想要的方式工作。

例如,如果我将 select 语句的这一部分写成如下:

SELECT
latest_balance
- (ISNULL (SUM(deposit) OVER(PARTITION BY account ORDER BY date DESC ROWS UNBOUNDED PRECEDING),0)
   + ISNULL (SUM(withdrawal)) OVER(PARTITION BY account ORDER BY date DESC ROWS UNBOUNDED PRECEDING),0))

这将返回如下内容:

account latest_balance date deposit withdrawal balance
XYZ 1 000 2021-07-16 100 900
XYZ 1 000 2021-07-15 200 700

这不是我希望看到的,因为第一行的余额应该是 1 000 而不是 900。我为此尝试了 ROWS、BETWEEN、UNBOUNDED、PRECEDING 和 FOLLOWING 的不同组合,但我仍然想不通了解如何使它工作。

有人可以分享您的知识并启发我吗?非常感谢! =)

【问题讨论】:

对于 mysql,请参见:this,对于 MSSQL,请参见:this。两者都解释了您应该(或希望?)了解的基本知识。 【参考方案1】:

您似乎希望 latest_balancedepositwithdrawal 的累积总和删除直到上一行

那就是:

select t.*,
       (latest_balance -
        coalesce(sum(deposit) over (partition by account order by date rows between unbounded preceding and 1 preceding), 0) +
        coalesce(sum(withdrawal) over (partition by account order by date rows between unbounded preceding and 1 preceding), 0)
       ) as balance
from t;

【讨论】:

以上是关于SQL窗口函数和运行总计的主要内容,如果未能解决你的问题,请参考以下文章

使用窗口函数在 Impala 中的总计列

计算值在分区上更改时的运行总计

在 SQL 中使用窗口函数运行“匹配”总数

窗口函数 ROW_NUMBER() 使用变量 RUNNING TOTAL 更改处理 ORDER BY

是否可以索引运行总计以加快窗口功能?

Hive sql及窗口函数