[英]SQL delta calculation with varying records
我正在計算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
也許試試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
使用此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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.