我正在计算calc_table
批次运行之间的金额差异,并将其存储在delta_table
中。每批次运行calc_table
的记录数可能会有所不同。
我可以计算差异,但我不知道如何处理新的或删除的记录,因为SQL中的JOINS会有所不同。我相信我需要使用FULL JOIN,但是我在构建SQL查询时遇到了问题。
注意:batch_id并不总是递增1.并且查询应该在calc_table
中,因为这是存储金额的地方。 delta_table
将包含calc_table数量之间的差异。
这是我目前的SQL :(我正在使用PostgreSQL)
select c2.batch_id, c2.c_id, c2.date,
(c2.amount1 - c1.amount1) as amount1, (c2.amount2 - c1.amount2) as amount2
from calc_table c1 inner join calc_table c2 on c1.c_id = c2.c_id
where c1.batch_id = 100 and c2.batch_id = 101
* c1.batch_id and c2.batch_id are PARAMETERS.
这给了我所有预期的c_id(删除和新记录)。但我无法正确构建它以给出我对delta计算的预期结果。
SELECT coalesce(c2.c_id, c1.c_id) as c_id
FROM
(select * from calc_table where batch_id = 100) c1
FULL OUTER JOIN
(select * from calc_table where batch_id = 101) c2
ON c1.id = c2.id
group by coalesce(c2.c_id, c1.c_id);
这是calc_table的第一次运行:(batch_id = 100)
calc_table:
-----------------------------------------------------
id | batch_id | c_id | date | amount1 | amount2
-----------------------------------------------------
1 | 100 | C001 | 2017-03-01 | 100 | 200
2 | 100 | C002 | 2017-03-01 | 100 | 200
3 | 100 | C003 | 2017-03-01 | 100 | 200
如果用户再次运行:(batch_id = 101)
4 | 101 | C001 | 2017-03-01 | 200 | 200
5 | 101 | C002 | 2017-03-01 | 150 | 220
6 | 101 | C003 | 2017-03-01 | 170 | 250
7 | 101 | C004*| 2017-03-01 | 210 | 250
* C004 is a new record
应计算它们之间的差值(batch_id 101减去100)并存储在delta_table中:
delta_table:
------------------------------------------------------
id | batch_id | c_id | date | amount1 | amount2
------------------------------------------------------
1 | 101 | C001 | 2017-03-01 | 100 | 0
2 | 101 | C002 | 2017-03-01 | 50 | 20
3 | 101 | C003 | 2017-03-01 | 70 | 50
4 | 101 | C004 | 2017-03-01 | 210 | 250
如果用户再次运行:(batch_id = 104,id 8-10)
* Rows 1-7 (same as before)
calc_table:
-----------------------------------------------------
id | batch_id | c_id | date | amount1 | amount2
-----------------------------------------------------
1 | 100 | C001 | 2017-03-01 | 100 | 200
2 | 100 | C002 | 2017-03-01 | 100 | 200
3 | 100 | C003 | 2017-03-01 | 100 | 200
4 | 101 | C001 | 2017-03-01 | 200 | 200
5 | 101 | C002 | 2017-03-01 | 150 | 220
6 | 101 | C003 | 2017-03-01 | 170 | 250
7 | 101 | C004 | 2017-03-01 | 210 | 250
8 | 104 | C001 | 2017-03-01 | 200 | 200
9 | 104 | C002 | 2017-03-01 | 400 | 200
10 | 104 | C003 | 2017-03-01 | 400 | 220
* Note: C004 was deleted
应计算它们之间的差值(batch_id 104减去101)并存储在delta_table中:
* Rows 1-4 (same as before), new delta = id 5-8
delta_table:
------------------------------------------------------
id | batch_id | c_id | date | amount1 | amount2
------------------------------------------------------
1 | 101 | C001 | 2017-03-01 | 100 | 0
2 | 101 | C002 | 2017-03-01 | 50 | 20
3 | 101 | C003 | 2017-03-01 | 70 | 50
4 | 101 | C004 | 2017-03-01 | 210 | 250
5 | 104 | C001 | 2017-03-01 | 0 | 0
6 | 104 | C002 | 2017-03-01 | 250 | -20
7 | 104 | C003 | 2017-03-01 | 230 | -30
8 | 104 | C004 | 2017-03-01 | -210 | -250
答案 0 :(得分:0)
也许试试FULL JOIN
?
假设你计算delta的batch_id总是增量为1.这样的东西:
SELECT COALESCE(new.batch_id, old_padded_with_deleted.batch_id) AS batch_id,
COALESCE(new.c_id, old_padded_with_deleted.c_id) AS c_id,
COALESCE(new.date, old_padded_with_deleted.date) AS date, --new.amount1, old_padded_with_deleted.amount1,
CASE WHEN new.amount1 IS NULL THEN -old_padded_with_deleted.amount1 ELSE (new.amount1 - coalesce(old_padded_with_deleted.amount1, 0)) END AS amount1,
CASE WHEN new.amount2 IS NULL THEN -old_padded_with_deleted.amount2 ELSE (new.amount2 - coalesce(old_padded_with_deleted.amount2, 0)) END AS amount2
FROM calc_table new
FULL JOIN (
SELECT coalesce(old.batch_id, deleted.batch_id)+1 AS batch_id, coalesce(old.c_id, deleted.c_id) AS c_id, coalesce(old.date, deleted.date) AS date,
coalesce(old.amount1, deleted.amount1) AS amount1, coalesce(old.amount2, deleted.amount2) AS amount2
FROM delta_table AS deleted
FULL JOIN calc_table AS old ON old.batch_id = deleted.batch_id AND old.c_id = deleted.c_id
) AS old_padded_with_deleted ON old_padded_with_deleted.c_id = new.c_id
AND old_padded_with_deleted.batch_id = new.batch_id
WHERE
new.batch_id = 101 OR old_padded_with_deleted.batch_id = 101
答案 1 :(得分:0)
使用此SQL解决了它:
select c1.c_id,
sum(case when c1.batch_id = 100 then (c1.amount1 * -1) else (c1.amount1 * 1) end) as amount1
from calc_table c1
where c1.batch_id = 100 or c1.batch_id = 101
group by c1.c_id