sql 年底取得余额
sql get balance at end of year
我有一个 一年 的交易 table,如果值为负或贷方交易值为正,则金额表示借方交易。
现在在给定的月份,如果借记记录数小于3或者一个月的借记总和小于100,那么我想收取5的费用。
我想在 postgre 中构建并sql查询:
select sum(amount), count(1), date_part('month', date) as month from transactions where amount < 0 group by month;
我可以按月获取记录,但我不知道如何进一步进行并获得结果。
这种方法怎么样?
SELECT
SUM(
CASE
WHEN usage.amount_s > 100
OR usage.event_c > 3
THEN 0
ELSE 5
END
) AS YEAR_FEE
FROM (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
) months
LEFT OUTER JOIN
(
SELECT
sum(amount) AS amount_s,
count(1) event_c,
date_part('month', date) AS month
FROM transactions
WHERE amount < 0
GROUP BY month
) usage ON months.month = usage.month;
您可以从使用 generate_series()
生成月份系列开始。然后将其与交易的聚合查询结合起来,最后在外部查询中实现业务逻辑:
select sum(t.balance)
- 5 * count(*) filter(where coalesce(t.cnt, 0) < 3 or coalesce(t.debit, 0) < 100) as balance
from generate_series(date '2020-01-01', date '2020-12-01', '1 month') as d(dt)
left join (
select date_trunc('month', date) as dt, count(*) cnt, sum(amount) as balance,
sum(-amount) filter(where amount < 0) as debit
from transactions t
group by date_trunc('month', date)
) t on t.dt = d.dt
| balance |
| ------: |
| 2746 |
首先,您必须使用 returns 所有月份 (1-12) 的结果集,并通过 LEFT
加入您的 table.
然后聚合得到每个月的金额之和,条件聚合从符合条件的月份减去5。
最后用SUM()
window函数对每个月的结果求和:
SELECT DISTINCT SUM(
COALESCE(SUM(t.Amount), 0) -
CASE
WHEN SUM((t.Amount < 0)::int) < 3
OR SUM(CASE WHEN t.Amount < 0 THEN -t.Amount ELSE 0 END) < 100 THEN 5
ELSE 0
END
) OVER () total
FROM generate_series(1, 12, 1) m(month) LEFT JOIN transactions t
ON m.month = date_part('month', t.date) AND date_part('year', t.date) = 2020
GROUP BY m.month
参见demo。
结果:
> | total |
> | ----: |
> | 2746 |
我想你可以使用 having 子句。
Select ( sum(a.total) - (12- count(b.cnt ))*5 ) as result From
(Select sum(amount) as total , 'A' as name from transactions ) as a left join
(Select count(amount) as cnt , 'A' as name
From transactions
where amount <0
group by month(date)
having not(count(amount) <3 or sum(amount) >-100) ) as b
on a.name = b.name
我有一个 一年 的交易 table,如果值为负或贷方交易值为正,则金额表示借方交易。
现在在给定的月份,如果借记记录数小于3或者一个月的借记总和小于100,那么我想收取5的费用。
我想在 postgre 中构建并sql查询:
select sum(amount), count(1), date_part('month', date) as month from transactions where amount < 0 group by month;
我可以按月获取记录,但我不知道如何进一步进行并获得结果。
这种方法怎么样?
SELECT
SUM(
CASE
WHEN usage.amount_s > 100
OR usage.event_c > 3
THEN 0
ELSE 5
END
) AS YEAR_FEE
FROM (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
) months
LEFT OUTER JOIN
(
SELECT
sum(amount) AS amount_s,
count(1) event_c,
date_part('month', date) AS month
FROM transactions
WHERE amount < 0
GROUP BY month
) usage ON months.month = usage.month;
您可以从使用 generate_series()
生成月份系列开始。然后将其与交易的聚合查询结合起来,最后在外部查询中实现业务逻辑:
select sum(t.balance)
- 5 * count(*) filter(where coalesce(t.cnt, 0) < 3 or coalesce(t.debit, 0) < 100) as balance
from generate_series(date '2020-01-01', date '2020-12-01', '1 month') as d(dt)
left join (
select date_trunc('month', date) as dt, count(*) cnt, sum(amount) as balance,
sum(-amount) filter(where amount < 0) as debit
from transactions t
group by date_trunc('month', date)
) t on t.dt = d.dt
| balance | | ------: | | 2746 |
首先,您必须使用 returns 所有月份 (1-12) 的结果集,并通过 LEFT
加入您的 table.
然后聚合得到每个月的金额之和,条件聚合从符合条件的月份减去5。
最后用SUM()
window函数对每个月的结果求和:
SELECT DISTINCT SUM(
COALESCE(SUM(t.Amount), 0) -
CASE
WHEN SUM((t.Amount < 0)::int) < 3
OR SUM(CASE WHEN t.Amount < 0 THEN -t.Amount ELSE 0 END) < 100 THEN 5
ELSE 0
END
) OVER () total
FROM generate_series(1, 12, 1) m(month) LEFT JOIN transactions t
ON m.month = date_part('month', t.date) AND date_part('year', t.date) = 2020
GROUP BY m.month
参见demo。
结果:
> | total |
> | ----: |
> | 2746 |
我想你可以使用 having 子句。
Select ( sum(a.total) - (12- count(b.cnt ))*5 ) as result From
(Select sum(amount) as total , 'A' as name from transactions ) as a left join
(Select count(amount) as cnt , 'A' as name
From transactions
where amount <0
group by month(date)
having not(count(amount) <3 or sum(amount) >-100) ) as b
on a.name = b.name