2017-06-19 144 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