簡體   English   中英

具有不同記錄的SQL增量計算

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM