【问题标题】:How to eliminate redundant values in sql calculation?如何消除sql计算中的冗余值?
【发布时间】:2021-09-21 22:03:48
【问题描述】:

我正在为美国的每个州创建月度收入报告。为简单起见,我将重点放在阿拉斯加。从下面的查询和结果可以看出,每张发票可以关联多个发票项:

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 中完成此操作。感谢您的任何指点!

【问题讨论】:

    标签: sql postgresql postgresql-9.4


    【解决方案1】:

    预聚合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;
    

    【讨论】:

      【解决方案2】:

      我使用了 Gordon Linoff 的答案,但我对客户表重复了 JOIN 语句,并将 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;
      

      【讨论】:

        猜你喜欢
        • 2021-02-15
        • 1970-01-01
        • 2011-03-13
        • 2020-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多