使用 SQL 计算交易余额

Calculating the Transaction Balance using SQL

问题: 您将获得一年的银行帐户历史记录。每笔交易要么是信用卡付款,要么是转账。持有信用卡需要每月支付一笔费用(5 美元)。但是,如果您在该月至少进行了三 (3) 次信用卡付款且总计至少 100 美元,则不会收取此金额。

目标: 计算年末余额

得到一个具有以下值的 table:

amount|date
-----------------
 1000 |2020-01-06
  -10 |2020-01-14
  -75 |2020-01-02
   -5 |2020-01-25
   -4 |2020-01-29
 2000 |2020-03-10
  -75 |2020-03-12
  -20 |2020-03-15
   40 |2020-03-15
  -50 |2020-03-17
  200 |2020-10-10
 -200 |2020-10-10

下面是创建 table:

的脚本
-- create a table
 create table transactions (
        amount integer not null,
        date date not null
  );
-- insert some values
INSERT INTO transactions VALUES (1000, '2020-01-06'), (-10, '2020-01-14'), (-75, '2020-01-20'), (-5, '2020-01-29'), (-4, '2020-01-29'), (2000, '2020-03-10'), (-75, '2020-03-12'), (-20, '2020-03-15'), (40, '2020-03-15'), (-50, '2020-03-17'), (200, '2020-10-10'), (-200, '2020-10-10');

**我非常接近,但我似乎无法找到一种方法来总结 sum_payments 的结果,**

-- fetch some values
WITH generated_months as(
  SELECT 1 as month UNION
  SELECT 2 UNION
  SELECT 3 UNION
  SELECT 4 UNION
  SELECT 5 UNION
  SELECT 6 UNION
  SELECT 7 UNION
  SELECT 8 UNION
  SELECT 9 UNION
  SELECT 10 UNION
  SELECT 11 UNION
  SELECT 12 ),
charges as(
  select sum(t1.amount) as sum_charges
      , count(1) as month_count
      , extract(month from date) as month
    from transactions t1
   where amount < 0),
   
 payments as(
  select sum(t2.amount) as sum_payments
      , EXTRACT(year from date) as year
      , count(1) month_count
    from transactions t2
   where amount > 0
   group by EXTRACT(year from date)
),
 fees as (
  select sum(CASE WHEN c.month_count >= 3 AND c.sum_charges <= -100
              THEN 0
              ELSE 5
               END            ) as calculated_fee
    from generated_months gm
    left join charges c on gm.month = c.month
)
select p.sum_payments - f.calculated_fee - c.sum_charges as FINAL_BALANCE
from payments p
cross join fees f
cross join charges c;

我被困在哪里:我试图通过尝试在主程序中执行以下操作来找到一种获取所有费用总和的方法(非 CTE) 查询 (p.sum_payments - f.calculated_fee - c.sum_charges);但是,我似乎无法找到 add/aggregate c.sum_charges 到我最终余额 (FINAL_BALANCE) 的方法...我在这里错过了什么?提前致谢!

期望输出:

FINAL_BALANCE|
-------------|
2746         |

2801 (Sum of all debits/credits +/-) - 55(fees from 11 months x  a month) = 46 (Final Balance)

您需要按月对数据进行分组,然后找出信用卡的借记次数,然后找出总金额并减去所需金额。

select sum(amount) - (12 - (select COUNT(*) FROM (SELECT date_trunc('month', date) AS month, sum(amount) as monthly_sum, count(amount) as monthly_count 
     FROM transactions WHERE amount<0
 GROUP BY month ) t where t.monthly_sum>=-100 and t.monthly_count>=3) ) * 5 as final_balance  from transactions

演示在 DBfiddle

下面 harvey 的解决方案并不适用于所有情况。这是三种不同情况下的正确解决方案:

您将从下面的 URL link 中找到三种不同的情况:

Example Test

案例可见于此:cases examples

with main as (
select
  date_trunc('month',date) as month, -- extracting months
  count(distinct date_trunc('month', date)) as total_months, -- counting total months
  sum(case when amount < 0 then amount else 0 end) as credit_amount, -- counting the negative balance per month since we need to need to check if it exceeds 100 or not.
  sum(case when amount < 0 then 1 else 0 end) as credit_count, --need to count the number of credited entries to check if the total number of those are greater or less than 3
  sum(amount) as total_balance
from transactions
group by 1
),
data as (
select
  *,
  case 
    when credit_amount <=  -100 and credit_count >= 3 -- when the number of credited (negative) entries are more or equal then 3 and sum up to -100 or less then no fee has to be paid for the credit card
   then total_balance else total_balance - 5  end as added_credit
from main
)
select 
  sum(added_credit) - ((12 - sum(total_months)) * (5)) 

from data