简体   繁体   English

获取具有多个连接的多列总和时如何防止重复

[英]How to prevent duplicates when getting sum of multiple columns with multiple joins

Lets say I have 3 tables: Invoices, Charges, and Payments.假设我有 3 个表:发票、费用和付款。 Invoices can have multiple charges, and charges can have multiple payments.发票可以有多项费用,费用可以有多次付款。

Doing a simple join, data would look like this:做一个简单的连接,数据看起来像这样:

invoiceid  |   chargeid   |  charge   |  payment
----------------------------------
1          |      1       |    50     |   50
2          |      2       |    100    |   25
2          |      2       |    100    |   75
2          |      3       |    30     |   10
2          |      3       |    30     |   5

If I do an join with sums,如果我加入总和,

select invoiceid, sum(charge), sum(payment)
from invoices i 
inner join charges c on i.invoiceid = c.invoiceid
inner join payments p on p.chargeid = c.chargeid
group by invoiceid

The sum of payments would be correct but charges would include duplicates:付款总和是正确的,但费用会重复:

invoiceid  |    charges   |   payments
--------------------------------------
1          |     50       |     50
2          |     260      |     115

I want a query to get a list of invoices with the sum of payments and sum of charges per invoice, like this:我想要一个查询来获取发票列表,其中包含每张发票的付款总和和费用总和,如下所示:

invoiceid  |    charges   |   payments
--------------------------------------
1          |     50       |     50
2          |     130      |     115

Is there any way to do this by modifying the query above WITHOUT using subqueries since subqueries can be quite slow when dealing with a large amount of data?有没有办法通过修改上面的查询而不使用子查询来做到这一点,因为在处理大量数据时子查询可能会非常慢? I feel like there must be a way to only include unique charges in the sum.我觉得必须有一种方法可以只在总和中包含独特的费用。

one way is to do the aggregation by the tables before the joins on the grouping value一种方法是在连接分组值之前通过表进行聚合

SELECT i.invoiceid, SumOfCharge, SumOfInvoice
FROM  invoices i 
INNER JOIN  (SELECT InvoiceID, suM(charges) sumOfCharges 
            FROM charges c 
            GROUP BY Invoiceid) c
   on i.invoiceid = c.invoiceid
INNER JOIN (SELECT invoiceid, sum(payment) as SumOfPayment
            FROM charages c
            INNER JOIN payments p on p.chargeid = c.chargeid
            GROUP BY Invoiceid) P
   on i.invoiceID = p.invoiceid

Another way would be to do it inline per invoice using correlation另一种方法是使用相关性对每张发票进行内联

SELECT i.invoiceid
     , (SELECT SUM(charge) FROM charges c WHERE c.invoiceid = i.invoiceid) SumOfCharge
     , SUM(Payment) SumOfInvoice
FROM  invoices i 
INNER JOIN  charges c 
   on i.invoiceid = c.invoiceid
INNER JOIN payments p 
   on p.chargeid = c.chargeid
GROUP BY Invoiceid

You can also achieve this by using LATERAL JOINS您还可以通过使用 LATERAL JOINS 来实现此目的

   SELECT
     i.invoiceid,
     chgs.total_charges,
     pays.total_payments
   FROM
     invoices AS i
     JOIN LATERAL (
        SELECT
            SUM( charge ) AS total_charges
        FROM
            charges AS c
        WHERE
            c.invoiceid = i.invoiceid
     ) AS chgs ON TRUE
     JOIN LATERAL (
        SELECT
            SUM( payment ) AS total_payments
        FROM
            payments AS p
        WHERE
            p.chargeid = c.chargeid
     ) AS pays ON TRUE

I hope this will help.我希望这将有所帮助。

select invoiceid, sum(distinct charge)as charges, sum(payment)as payments from yourtable group by invoiceid; select invoiceid, sum(distinct charge)as charges, sum(payment)as payments from yourtable group by invoiceid;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM