SQL 基于 WHERE 子句的 SUM 和 GROUP BY

SQL SUM and GROUP BY based on WHERE clause

我正在 运行ning PostgreSQL 9.4 并且具有以下 table 发票结构:

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 =  and time between '2017-06-01' and '2017-07-01' and status = 'done'

但这并没有考虑是否存在尚未关闭的正在进行的发票。

我怎样才能同时计算最大的 billing_id 没有状态 done

希望它有意义。

每张发票(即 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子句表示排名。

select sum (amount), id
from (
    select distinct on (billing_id) *
    from (
        select distinct on (status, billing_id) *
        from invoice_records
        where
            id = 
            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