SQL 修改累计值

SQL 修改累计值,你想依据另一列的值来修改累计值。试想这样的场景:你希望显示一个信用卡账户的交易历史,并显示每一笔交易完成后的余额。本实例将会用到如下所示的视图 V

SQL 修改累计值 问题描述

你想依据另一列的值来修改累计值。试想这样的场景:你希望显示一个信用卡账户的交易历史,并显示每一笔交易完成后的余额。本实例将会用到如下所示的视图 V

create view V (id,amt,trx)
as
select 1, 100, 'PR' from t1 union all
select 2, 100, 'PR' from t1 union all
select 3, 50,  'PY' from t1 union all
select 4, 100, 'PR' from t1 union all
select 5, 200, 'PY' from t1 union all
select 6, 50,  'PY' from t1
 
select * from V
 
ID        AMT TRX
-- ---------- ---
 1        100  PR
 2        100  PR
 3         50  PY
 4        100  PR
 5        200  PY
 6         50  PY

ID 列能唯一地标示每一笔交易。AMT 列代表每一笔交易涉及的金额(要么是还款,要么是购物)。TRX 列定义交易的类型:还款是 PY,购物是 PR。如果 TRX 的值是 PY,你希望能从累计值里减去当前的 AMT 值。如果 TRX 的值是 PR,你希望累计值加上当前的 AMT 值。最终,你想得到如下所示的结果集。

TRX_TYPE        AMT    BALANCE
-------- ---------- ----------
PURCHASE        100        100
PURCHASE        100        200
PAYMENT          50        150
PURCHASE        100        250
PAYMENT         200         50
PAYMENT          50          0

SQL 修改累计值 解决方案

DB2 和Oracle
使用窗口函数 SUM OVER 进行累计求和,并使用 CASE 表达式来决定交易的类型。

 1  select case when trx = 'PY'
 2              then 'PAYMENT'
 3              else 'PURCHASE'
 4          end trx_type,
 5          amt,
 6          sum(
 7           case when trx = 'PY'
 8              then -amt else amt
 9           end
10         ) over (order by id,amt) as balance
11    from V

MySQLPostgreSQLSQL Server
使用标量子查询进行累计求和,并使用 CASE 表达式来决定交易的类型。

 1  select case when v1.trx = 'PY'
 2              then 'PAYMENT'
 3              else 'PURCHASE'
 4          end as trx_type,
 5          v1.amt,
 6          (select sum(
 7                   case when v2.trx = 'PY'
 8                        then -v2.amt else v2.amt
 9                   end
10                 )
11            from V v2
12           where v2.id <= v1.id) as balance
13   from V v1

SQL 修改累计值 扩展知识

CASE 表达式用于决定是把当前的 AMT 值加到累计值中,还是从累计值中减去当前的 AMT 值。如果交易类型是还款,AMT 值会被变为负数,因而相应的累计值会减少。CASE 表达式的结果如下所示。

select case when trx = 'PY'
            then 'PAYMENT'
            else 'PURCHASE'
       end trx_type,
       case when trx = 'PY'
            then -amt else amt
       end as amt
  from V
 
TRX_TYPE       AMT
-------- ---------
PURCHASE       100
PURCHASE       100
PAYMENT        -50
PURCHASE       100
PAYMENT       -200
PAYMENT        -50

依据交易类型的评估结果,AMT 值会被加入累计值,或者从累计值中减去。关于如何使用窗口函数 SUM OVER 或者标量子查询进行累计求和,请参考 7.6 节。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

SQL 实例