[英]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.