每笔交易后的余额计算

时间:2013-08-28 17:35:53

标签: sql

我有这样的表:

cust_id acc_no trans_id  trans_type amount
1111    1001    10   credit     2000.0  
1111    1001    11   credit     1000.0
1111    1001    12   debit      1000.0  
2222    1002    13   credit     2000.0  
2222    1002    14   debit      1000.0

我希望对客户完成的每笔交易进行Hive查询或SQL查询,以便计算余额。

我想要输出如下:

cust_id acc_no trans_id  trans_type amount      balance
1111.0  1001.0  10.0     credit    2000.0   2000.0
1111.0  1001.0  11.0     credit    1000.0   3000.0
1111.0  1001.0  12.0     debit     1000.0   2000.0
2222.0  1002.0  13.0     credit    2000.0   2000.0
2222.0  1002.0  14.0     debit     1000.0   1000.0

我试过

SELECT * 
FROM   (SELECT cust_id, 
               acc_no, 
               trans_id, 
               trans_type, 
               amount, 
               CASE 
                 WHEN Trim(trans_type) = 'credit' THEN ball = 
                 Trim(bal) + Trim(amt) 
                 ELSE ball = Trim(bal) - Trim(amt) 
               end 
        FROM   ban) l; 

6 个答案:

答案 0 :(得分:3)

此查询可以解决问题:

SELECT t1.cust_id,t1.acc_no,t1.trans_id,t1.trans_type,t1.amount,
       sum(t2.amount*case when t2.trans_type = 'credit' then 1 
                             else -1 end) as balance
FROM Table1 t1
INNER JOIN Table1 t2 ON t1.cust_id = t2.cust_id AND 
                        t1.acc_no = t2.acc_no AND 
                        t1.trans_id >= t2.trans_id
GROUP BY t1.cust_id,t1.acc_no,t1.trans_id,t1.trans_type,t1.amount

请参阅SQLFIDDLE:http://www.sqlfiddle.com/#!2/3b5d8/15/0

编辑: SQL Fiddle

MySQL 5.5.32架构设置

CREATE TABLE Table1
    (`cust_id` int, `acc_no` int, `trans_id` int, 
     `trans_type` varchar(6), `amount` int)
;

INSERT INTO Table1
    (`cust_id`, `acc_no`, `trans_id`, `trans_type`, `amount`)
VALUES
    (1111, 1001, 10, 'credit', 2000.0),
    (1111, 1001, 11, 'credit', 1000.0),
    (1111, 1001, 12, 'debit', 1000.0),
    (2222, 1002, 13, 'credit', 2000.0),
    (2222, 1002, 14, 'debit', 1000.0)
;

查询1

SELECT t1.cust_id,t1.acc_no,t1.trans_id,t1.trans_type,t1.amount,
       sum(t2.amount*case when t2.trans_type = 'credit' then 1 
                             else -1 end) as balance
FROM Table1 t1
INNER JOIN Table1 t2 ON t1.cust_id = t2.cust_id AND 
                        t1.acc_no = t2.acc_no AND 
                        t1.trans_id >= t2.trans_id
GROUP BY t1.cust_id,t1.acc_no,t1.trans_id,t1.trans_type,t1.amount

<强> Results

| CUST_ID | ACC_NO | TRANS_ID | TRANS_TYPE | AMOUNT | BALANCE |
|---------|--------|----------|------------|--------|---------|
|    1111 |   1001 |       10 |     credit |   2000 |    2000 |
|    1111 |   1001 |       11 |     credit |   1000 |    3000 |
|    1111 |   1001 |       12 |      debit |   1000 |    2000 |
|    2222 |   1002 |       13 |     credit |   2000 |    2000 |
|    2222 |   1002 |       14 |      debit |   1000 |    1000 |

答案 1 :(得分:0)

您可以通过View轻松完成此操作,可以直接在表上计算,但会导致性能和可伸缩性问题(随着表的增长,数据库将变慢)。通过使用View,可以根据需要执行计算;如果您对视图编制索引,则可以使余额保持最新,而不会影响事务表的性能。

如果您确实坚持将其置于事务表本身中,则可以使用运行用户定义函数的计算列来确定当前余额。但是,这将取决于您正在使用的特定SQL后端。


这是一个基本的SELECT语句,它按帐户计算当前余额:

select
acc_no, 
sum(case trans_type 
    when 'credit' then amount 
    when 'debit' then amount * -1 
    end) as Amount 
from Transactions
group by acc_no

答案 2 :(得分:0)

您可以使用窗口功能:

select cust_id, 
acc_no, trans_id, trans_type, amount, 
sum(pre_balance) over (partition by cust_id order by trans_id) as balance
from    
(select cust_id, acc_no, trans_id, trans_type, 
        amount, 
        amount as pre_balance from test 
        where trans_type = 'credit' 
 union
 select cust_id, acc_no, trans_id, trans_type, 
        amount, -amount as pre_balance from 
        test where trans_type = 'debit'
 order by trans_id) as sub;

答案 3 :(得分:0)

with current_balances as (
SELECT
       id,
       user_id,
       SUM(amount) OVER (PARTITION BY user_id ORDER BY created ASC) as current_balance
FROM payments_transaction pt
ORDER BY created DESC
)
SELECT
    pt.id,
    amount,
    pt.user_id,
    cb.current_balance as running_balance
FROM
    payments_transaction pt
INNER JOIN
    current_balances cb
ON pt.id = cb.id
ORDER BY created DESC
LIMIT 10;

这对于获得高额回报非常有效,并且不会因过滤或限制而中断。请注意,如果仅选择一个用户或其中一部分用户,请在user_id cte中提供current_balances过滤器,并在主要选择中省略整个表扫描。

答案 4 :(得分:0)

一种简单的解决方案是基于trans_type量化每个交易(-或+),然后使用窗口函数获得累计金额。

SELECT cust_id, 
   acc_no, 
   trans_id, 
   trans_type, 
   amount, 
   Sum (real_amount) 
     OVER (ORDER BY cust_id) AS balance 
FROM   (SELECT cust_id, 
           acc_no, 
           trans_id, 
           trans_type, 
           amount, 
           ( CASE trans_type 
               WHEN 'credit' THEN amount 
               WHEN 'debit' THEN amount *- 1 
             END ) AS real_amount 
    FROM   test) t

答案 5 :(得分:0)

表(交易) —— “id” “金额” “is_credit”

1 10000 1
2 2000 0
3 5000 1

查询:

选择 * 从 ( SELECT id, amount, SUM(CASE When is_credit=1 Then amount Else -amount End) OVER (ORDER BY id) AS balance 从`交易` GROUP BY id,金额 ) 按 ID 排序;

输出:

“id”“金额”“is_credit”“余额”

1 10000 1 10000

2 2000 0 8000

3 5000 1 13000