如何去除sql计算中的冗余值?

How to eliminate redundant values in sql calculation?

我正在为 U.S 中的每个州创建月度收入报告。为简单起见,我专注于阿拉斯加。从下面的查询和结果中,您可以看到每个发票可以与多个发票项目相关联:

SELECT
   i.id AS "i.id",
   i.subtotal,
   i.credit,
   i.tax,
   ii.id AS "ii.id",
   ii.refunded_amount
FROM
   invoices i
   JOIN customer ON i.customer_id = customer.id
   JOIN invoice_items ii ON i.id = ii.invoices_id
WHERE
   i.status = 'Paid'
   AND i.datepaid BETWEEN '2016-01-01' AND '2016-02-01'
   AND customer.billing_day <> 0
   AND customer.register_date < '2016-02-01'
   AND customer.account_exempt = 'f'
   AND customer.country = 'US'
   AND customer.state = 'AK';

  i.id   | subtotal | credit |  tax  | ii.id  | refunded_amount 
----------+----------+--------+-------+--------+-----------------
27111851 |      100 |      0 |    20 | 746219 |               0
27111851 |      100 |      0 |    20 | 746218 |              15
27111851 |      100 |      0 |    20 | 746217 |               0
27111852 |        0 |      1 |     0 | 746217 |               0
27111853 |      200 |      0 |    40 | 746220 |               0

我想列出阿拉斯加州每月的销售额、税收和总收入。 下面是我写的查询和结果:

SELECT
    customer.state AS "State",
    ROUND((SUM(i.subtotal - i.credit)):: NUMERIC, 2) AS "Sales",
    ROUND((SUM(i.tax)):: NUMERIC, 2) AS "Tax",
    ROUND(
        (
            SUM((i.subtotal - i.credit + i.tax) - ii.refunded_amount)
        ):: NUMERIC,
        2
    ) AS "Gross"
FROM
    invoices i
    JOIN customer ON i.customer_id = customer.id
    JOIN invoice_items ii ON i.id = ii.invoices_id
WHERE
    i.status = 'Paid'
    AND i.datepaid BETWEEN '2016-01-01' AND '2016-02-01'
    AND customer.billing_day <> 0
    AND customer.register_date < '2016-02-01'
    AND customer.account_exempt = 'f'
    AND customer.country = 'US'
    AND customer.state = 'AK'
GROUP BY
    customer.state;

 State |  Sales  |  Tax   |  Gross    
-------+---------+--------+----------
 AK    |     499 |   100  |      584 

下面是结果应该是什么:

 State |  Sales  |  Tax   |  Gross    
-------+---------+--------+----------
 AK    |     299 |    60  |      344 

我的查询多次将相同的发票小计、税金和贷记制成表格,这人为地夸大了结果。我需要更改查询,以便它仅将每张发票合并到计算中一次,但仍会查看所有关联的发票项目。我不确定如何在 sql 中完成此操作。感谢指点!

预聚合 invoice_items,因此不会影响其他结果:

SELECT c.state AS "State",
       ROUND((SUM(i.subtotal - i.credit)):: NUMERIC, 2) AS "Sales",
       ROUND((SUM(i.tax)):: NUMERIC, 2) AS "Tax",
       ROUND(SUM((i.subtotal - i.credit + i.tax) - ii.refunded_amount):: NUMERIC, 2
            ) AS "Gross"
FROM invoices i JOIN
     customer c
     ON i.customer_id = c.id JOIN
     (SELECT ii.invoices_id, SUM(ii.refunded_amount) as refunded_amount
      FROM invoice_items ii
      GROUP BY ii.invoiced_id
     ) ii
     ON i.id = ii.invoices_id
WHERE i.status = 'Paid' AND
      i.datepaid BETWEEN '2016-01-01' AND '2016-02-01' AND
      c.billing_day <> 0 AND
      c.register_date < '2016-02-01' AND
      c.account_exempt = 'f' AND
      c.country = 'US' AND
      c.state = 'AK'
GROUP BY c.state;

我使用了 Gordon Linoff 的回答,但我与客户重复了 JOIN 语句 table 并将 WHERE 子句移动到子查询中。

    SELECT
        customer.state AS "State",
        ROUND((SUM(i.subtotal - i.credit)):: NUMERIC, 2) AS "Sales",
        ROUND((SUM(i.tax)):: NUMERIC, 2) AS "Tax",
        ROUND(
            SUM((i.subtotal - i.credit + i.tax) - refunded_amount):: NUMERIC,
            2
        ) AS "Gross"
    FROM
        invoices i
        JOIN customer ON i.customer_id = customer.id
        JOIN (
            SELECT
                ii.invoices_id,
                SUM(ii.refunded_amount) AS refunded_amount
            FROM
                invoices i
                JOIN customer ON i.customer_id = customer.id
                JOIN invoice_items ii ON i.id = ii.invoices_id
            WHERE
                i.datepaid BETWEEN '2016-01-01' AND '2016-02-01' AND
                customer.billing_day <> 0 AND
                customer.register_date < '2016-02-01' AND
                customer.account_exempt = 'f' AND
                customer.country = 'US' AND
                customer.state = 'AK'
            GROUP BY
                ii.invoices_id
        ) ii ON i.id = ii.invoices_id
    GROUP BY customer.state;