2017-06-19 149 views
0

我運行的PostgreSQL 9.4和具有以下表結構的發票:SQL SUM和GROUP BY基於WHERE子句

id BIGINT, time UNIX_TIMESTAMP, customer TEXT, amount BIGINT, status TEXT, billing_id TEXT 

我希望我能正確地解釋我的挑戰。

發票記錄可以有2個不同的狀態; beginongoingdone。 隨着時間的推移,多個發票記錄可以成爲同一發票行的一部分。

因此,當發票期開始時,記錄開始時的狀態爲begin。 然後每6小時會產生一個新的記錄,其狀態爲ongoing,其中包含amount中的當前金額支出。 發票關閉時,會生成狀態爲done的記錄,並在欄位amount中的總金額支出中生成。同一發票內的所有發票記錄包含相同的billing_id

要calcuate一個客戶目前的開支,我可以運行以下命令:

SELECT sum(amount) FROM invoice_records where id = $1 and time between '2017-06-01' and '2017-07-01' and status = 'done' 

但是,如果有一個持續的發票中尚未關閉,不考慮。

我怎樣才能算出最大的billing_id沒有狀態done

希望它有道理。

+1

如果每個'id'只有一個'status ='done'',你爲什麼要做sum()?不僅僅是'SELECT amount FROM'還是我錯過了什麼? –

+0

在我的示例中,我總結了特定客戶的所有發票(「d')。 –

+0

您在此表中稱客戶ID爲ID?你不應該。稱爲ID的列應該唯一標識表中的記錄。如果您需要該表中的客戶ID,請將其稱爲customer_id或類似名稱。 –

回答

1

每張發票(即billing_id)你想記錄的量與status = 'done'如果這樣的存在,或者與status = 'ongoing'最後一條記錄。您可以使用PostgreSQL的DISTINCT ON(或使用標準SQL的ROW_NUMBER對每張發票的記錄進行排名)。

SELECT DISTINCT ON (billing_id) billing_id, amount 
FROM invoice_records 
WHERE status IN ('done', 'ongoing', 'begin') 
ORDER BY 
    billing_id, 
    CASE status WHEN 'done' THEN 1 WHEN 'ongoing' THEN 2 ELSE 3 END, 
    unix_timestamp desc; 

ORDER BY子句代表排名。

+0

相同的'billing_id'可以包含1個'begin',X''正在執行中'和1個'done'記錄。開始'也可以包含'amount',並且可以有多個10+個記錄與'進行中' –

+0

好吧,所以你也對status ='begin'感興趣,這是一個簡單的改變。這就是爲什麼我爲每個billing_id選擇一條記錄;最好是1完成,否則最新的正在進行,我會更新以獲取狀態=開始考慮到 –

+0

DISTINCT ON(billing_id),billing_id'做什麼,似乎dublicate 「我在語法錯誤處或附近」,「''near'SELECT DISTINCT ON(billing_id),billing_id' –

0
select sum (amount), id 
from (
    select distinct on (billing_id) * 
    from (
     select distinct on (status, billing_id) * 
     from invoice_records 
     where 
      id = $1 
      and time between '2017-06-01' and '2017-07-01' 
      and status in ('done', 'ongoing') 
     order by status, billing_id desc 
    ) s 
    order by billing_id desc 
) s