SQL SUM和GROUP BY基于WHERE子句

时间:2017-06-19 13:38:46

标签: sql postgresql postgresql-9.4

我正在运行PostgreSQL 9.4并具有以下表结构用于开发票:

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

我希望我能正确解释我的挑战。

发票记录可以有2种不同的状态; beginongoingdone。 随着时间的推移,多个发票记录可以成为同一发票行的一部分。

因此,当发票期间开始时,将启动状态为begin的记录。 然后,每隔6小时生成一条状态为ongoing的新记录,其中包含amount中的当前金额。 关闭发票后,会生成状态为done的记录,其中包含amount列中的总金额。同一发票中的所有发票记录都包含相同的billing_id

要计算客户目前的支出,我可以执行以下操作:

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

但是,如果还有尚未结算的正在进行的发票,则不会考虑这一点。

如何计算没有状态done的最大billing_id?

希望它有意义。

2 个答案:

答案 0 :(得分: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子句代表排名。

答案 1 :(得分: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