Using Multiple Joins. Sum() Producing Wrong Value

Using multiple JOINS. SUM() producing wrong value

If you run the query without a group by, you'll see that some payments have multiple rows. That's because you're also joining on order items. The result set will contain a row for each combination of orderitem and payment.

One solution would be to change the sum to:

,    <earlier columns>    
, ( select SUM(payments.amount)
from payments
where payments.orderID = orders.id
) AS totalPayments
, <later columns>

This would ensure the payments with multiple orderitems are not summed multiple times.

Getting correct sums with multiple joins

The subquery idea untested

SELECT PNR, isnull(CR.CREDITS,0) AS CREDITS,
...
FROM DATABASE.PERSON P
LEFT OUTER JOIN (
SELECT CRQ.PERSON_ID, SUM(C.CREDIT) AS CREDITS
-- I'm not really sure how to associate a person with the credits
-- but hopefully you'll get the idea here.
FROM DATABASE.PICKED_COURSE PCO
INNER JOIN DATABASE.COURSE_REG_QUAL CRQ on CRQ.COURSE_ID=C.COURSE_ID
GROUP BY CRQ.PERSON_ID
) CR on CR.PERSON_ID = P.PERSON_ID
LEFT JOIN DATABASE.PERSON_ADDRESS PA ON P.PERSON_ID=PA.PERSON_ID
LEFT JOIN DATABASE.DIPLOMA DU ON P.PERSON_ID=DU.PERSON_ID
...

Problems with multiple joins and a sum

You would typically pre-aggregate in subqueries before joining, like so:

SELECT p.*
COALESCE(v.voteCount, 0) as voteCount,
COALESCE(v.userVote, 0) as userVote,
COALESCE(c.numComments, 0) as numComments
FROM post p
LEFT JOIN (
SELECT postID,
SUM(vote) as voteCount,
SUM(vote) FILTER (WHERE username = :username) userVote
FROM votes
GROUP BY postID
) v ON v.postID = p.postID
LEFT JOIN (
SELECT postID, count(*) numComments
FROM comments
WHERE parentID IS NULL
GROUP BY postID
) c ON c.postID = p.postID
ORDER BY voteCount DESC

N1QL Multiple join and sum query producing wrong output

JOINS can expand the original rows. During first Join left most document is expanded. You are using first document field as second join condition that can produce multiple documents same condition. This how semantics works. You need to adjust your join condition based on the needs.

The second JOIN uses one document from the LEFT most. SUM over DISTINCT may not work because different documents same value (warm_coffee, may under count) is counted once. If I am right you are looking second join to use unique document from LEFT most coffee.

May be you are looking some thing like this

SELECT c.coffeeId,
MAX(c.ccNumber) AS `ccNumber`,
SUM(warm_coffee.`number`) AS `wcNumber`,
FROM ( SELECT META(coffee).id AS coffeeId,
SUM(cold_coffee.`number`) AS `ccNumber`
FROM coffee_bucket coffee
LEFT JOIN coffee_bucket cold_coffee
ON META(coffee).id = cold_coffee.coffeeId AND cold_coffee.type='cold_coffee'
WHERE coffee.type='coffee'
GROUP BY META(coffee).id
) AS c
LEFT JOIN coffee_bucket warm_coffee
ON c.coffeeId = warm_coffee.coffeeId AND warm_coffee.type='warm_coffee'
GROUP BY c.coffeeId;

3 level join

SELECT d.coffeeId,
MAX(c.ccNumber) AS `ccNumber`,
MAX(c.wcNumber) AS `wcNumber`,
SUM(ch.`number`) AS `chNumber`
FROM ( SELECT c.coffeeId,
MAX(c.ccNumber) AS `ccNumber`,
SUM(warm_coffee.`number`) AS `wcNumber`,
FROM ( SELECT META(coffee).id AS coffeeId,
SUM(cold_coffee.`number`) AS `ccNumber`
FROM coffee_bucket coffee
LEFT JOIN coffee_bucket cold_coffee
ON META(coffee).id = cold_coffee.coffeeId AND cold_coffee.type='cold_coffee'
WHERE coffee.type='coffee'
GROUP BY META(coffee).id
) AS c
LEFT JOIN coffee_bucket warm_coffee
ON c.coffeeId = warm_coffee.coffeeId AND warm_coffee.type='warm_coffee'
GROUP BY c.coffeeId) AS d
LEFT JOIN coffee_bucket ch
ON d.coffeeId = ch.coffeeId AND ch.type='chaoc_coffee'
GROUP BY d.coffeeId
;

Incorrect sum when I join a second table

Group records per date using following

SELECT ReportSummary.ReportDate, SUM(ReportSummary.SumHeadCount) AS SumHeadCount, SUM(ProductionSummary.SumQuantity) AS SumQuantity
FROM
(
SELECT Report.ReportDate, SUM(Report.HeadCount) AS SumHeadCount
FROM Report
GROUP BY Report.ReportDate
) AS ReportSummary
INNER JOIN
(
SELECT Report.ReportDate, Sum(Production.Quantity) AS SumQuantity
FROM Production
INNER JOIN Report
ON Report.ReportID = Production.ReportID
GROUP BY Report.ReportDate
) AS ProductionSummary
ON ReportSummary.ReportDate = ProductionSummary.ReportDate
GROUP BY ReportSummary.ReportDate
ORDER BY ReportSummary.ReportDate

MySQL: SUM() with JOIN returns incorrect values

Try this query:

SELECT bl.user_id, SUM( ph.amount ) PAIDOUT
FROM (
SELECT distinct blocks.user_id
FROM blocks
WHERE confirms > 520
) bl
LEFT JOIN payout_history ph
ON bl.user_id = ph.user_id
GROUP BY ph.user_id
;

SQLFiddle --> http://sqlfiddle.com/#!2/7b988/48


--- EDIT --- an explanation how the query works (or rather why your query doesn't work) ----

Looking at expected results it seems that the query should calculate a sum of amount column for each user_id, but only for those user_id, that are also in the blocks table, and have a blocks.confirms value grather than 520.

A simple join (also left outer join) cannot work in this case, because the blocks table can contain many records for the same user_id, for example a query that returns rows for only user_id=110 gives the following results:

SELECT *
FROM blocks
WHERE confirms > 520
AND user_id = 110;

+ ------- + ------------ + ----------- + ------------- +
| id | user_id | reward | confirms |
+ ------- + ------------ + ----------- + ------------- +
| 0 | 110 | 20.89832115 | 521 |
| 65174 | 110 | 3.80357075 | 698 |
| 65204 | 110 | 4.41933060 | 668 |
| 65218 | 110 | 4.69059801 | 654 |
| 65219 | 110 | 4.70222521 | 653 |
| 65230 | 110 | 4.82805490 | 642 |
| 65265 | 110 | 5.25058079 | 607 |
| 65316 | 110 | 6.17262650 | 556 |
+ ------- + ------------ + ----------- + ------------- +

The straigh join (and LEFT/RIGHT outer join) works in this way, that takes each record from the first joinded table, and pair this record (combine it) with all rows from the other joinded table thet meet the join condition.

In our case the left join produces a below resultset:

SELECT *
FROM blocks
LEFT JOIN payout_history
ON blocks.user_id = payout_history.user_id
WHERE confirms > 520
AND blocks.user_id = 110;
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +
| id | user_id | reward | confirms | id | user_id | amount |
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +
| 0 | 110 | 20.89832115 | 521 | 1 | 110 | 20.898319 |
| 65174 | 110 | 3.80357075 | 698 | 1 | 110 | 20.898319 |
| 65204 | 110 | 4.41933060 | 668 | 1 | 110 | 20.898319 |
| 65218 | 110 | 4.69059801 | 654 | 1 | 110 | 20.898319 |
| 65219 | 110 | 4.70222521 | 653 | 1 | 110 | 20.898319 |
| 65230 | 110 | 4.82805490 | 642 | 1 | 110 | 20.898319 |
| 65265 | 110 | 5.25058079 | 607 | 1 | 110 | 20.898319 |
| 65316 | 110 | 6.17262650 | 556 | 1 | 110 | 20.898319 |
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +

and now if we add SUM( amount ) .... GROUP BY user_id, MySql will calucate a sum of all amount values from the above resultset ( 8 rows * 20.898 = ~ 167.184 )

SELECT blocks.user_id, sum( amount)
FROM blocks
LEFT JOIN payout_history
ON blocks.user_id = payout_history.user_id
WHERE confirms > 520
AND blocks.user_id = 110
GROUP BY blocks.user_id;
+ ------------ + ----------------- +
| user_id | sum( amount) |
+ ------------ + ----------------- +
| 110 | 167.186554 |
+ ------------ + ----------------- +


As you see in this case the join doesn't give us desired results - we need something named a semi join - below are different variants of semi joins, give them a try:

SELECT bl.user_id, SUM( ph.amount ) PAIDOUT
FROM (
SELECT distinct blocks.user_id
FROM blocks
WHERE confirms > 520
) bl
LEFT JOIN payout_history ph
ON bl.user_id = ph.user_id
GROUP BY ph.user_id
;

SELECT ph.user_id, SUM( ph.amount ) PAIDOUT
FROM payout_history ph
WHERE ph.user_id IN (
SELECT user_id FROM blocks
WHERE confirms > 520
)
GROUP BY ph.user_id
;

SELECT ph.user_id, SUM( ph.amount ) PAIDOUT
FROM payout_history ph
WHERE EXISTS (
SELECT 1 FROM blocks bl
WHERE bl.user_id = ph.user_id
AND bl.confirms > 520
)
GROUP BY ph.user_id
;

Mysql sum query returning incorrect result when using multiple joins

Use the totals directly because your joins are probably creating more rows in combination that you want.

Try the following:

SELECT id, MAX(Total) as FinalTotal ,MAX(Payment) as FinalPayment
FROM si_invoices a
left join
(select invoice_id, sum(total) as Total from si_invoice_items group by invoice_id) b
on a.id = b.invoice_id
left join
(select ac_inv_id, sum(payment) as Payment from si_payment group by ac_inv_id) c
on c.ac_inv_id = a.id
group by id

or if id is unique:

    SELECT *
FROM si_invoices a
left join
(select invoice_id, sum(total) as Total from si_invoice_items group by invoice_id) b
on a.id = b.invoice_id
left join
(select ac_inv_id, sum(payment) as Payment from si_payment group by ac_inv_id) c
on c.ac_inv_id = a.id

SQL multiple tables join problem with SUM Results Multiples times Higher Value

Records count are differing each tables, that's why value increasing due to duplication of records, to avoid this take sum before joining a tables,. It will give better results and also your expected result also wrong for the sample data.

Suggestion: To better result you can replace RIGHT OUTER JOIN with LEFT OUTER JOIN.

Here is the code:

--------Table Creation Part-----
CREATE TABLE #tblretailer
(
ID INT,
[NAME] VARCHAR(50),
PLACE VARCHAR(25),
PHONE VARCHAR(10),
)
GO

CREATE TABLE #tbldraw
(
ID INT,
RetailerID INT,
DrawNumber INT,
[Count] INT,
CreatedDate DATE
)
GO

CREATE TABLE #Tbl_ABC
(
ID INT,
RetailerID INT,
ANum INT,
BNum INT,
CNum INT,
ACount INT,
BCount INT,
CCount INT,
CreatedDate DATE
)
GO

CREATE TABLE #Tbl_ABACBC
(
ID INT,
RetailerID INT,
ANum INT,
BNum INT,
CNum INT,
ABCount INT,
ACCount INT,
BCCount INT,
CreatedDate DATE
)
GO

/*
DROP TABLE #tblretailer, #tbldraw, #Tbl_ABC, #Tbl_ABACBC
GO
*/
-----Value Insert-------
INSERT INTO #tblretailer
SELECT 3, 'Zen Commmunications','Navi mumbai','3456728102'
UNION ALL
SELECT 4, 'ASpire Systems','New Delhi','4324535453'
UNION ALL
SELECT 5, 'Zen Commmunications','New Delhi','4324535454'
GO

INSERT INTO #tbldraw
SELECT 2368, 4, 123, 10, '2020-06-01'
UNION ALL
SELECT 2370, 4, 777, 15, '2020-06-01'
UNION ALL
SELECT 2371, 3, 153, 100, '2020-06-01'
UNION ALL
SELECT 2372, 3, 758, 50, '2020-06-01'
UNION ALL
SELECT 2374, 3, 777, 10, '2020-06-01'
GO

INSERT INTO #Tbl_ABC
SELECT 21, 4, 1, 2, 3, 10, 5, 15, '2020-06-01'
UNION ALL
SELECT 22, 4, 1, 2, 3, 10, 20, 15, '2020-06-01'
UNION ALL
SELECT 23, 3, 1, 2, 3, 10, 25, 0, '2020-06-01'
UNION ALL
SELECT 24, 3, 1, 2, 3, 80, 0, 0, '2020-06-01'
UNION ALL
SELECT 25, 3, 1, 2, 3, 10, 5, 20, '2020-06-01'
GO

INSERT INTO #Tbl_ABACBC
SELECT 9, 4, 12, 20, 30, 10, 10, 10, '2020-06-01'
UNION ALL
SELECT 10, 4, 12, 20, 30, 15, 15, 15, '2020-06-01'
UNION ALL
SELECT 11, 3, 12, 20, 30, 15, 20, 0, '2020-06-01'
UNION ALL
SELECT 12, 3, 12, 20, 30, 0, 10, 20, '2020-06-01'
GO

----Query Part-----
DECLARE @Date DATE = '2020-06-01'

SELECT
RETAILER.id,
NAME AS retailername,
atotal,
Btotal,
Ctotal,
strtotal,
-- SUM(ISNULL(boxcount, 0)) AS boxtotal,
abtotal,
actotal,
bctotal
FROM
#tblretailer AS RETAILER
RIGHT JOIN
(
SELECT
ABC.retailerid
, SUM(ISNULL(acount, 0)) AS atotal
, SUM(ISNULL(bcount, 0)) AS Btotal
, SUM(ISNULL(ccount, 0)) AS Ctotal
FROM
#tbl_abc AS ABC
WHERE
ISNULL(ABC.createddate, CAST(GETDATE() AS DATE)) = @Date
GROUP BY
ABC.retailerid
) AS ABC ON ABC.retailerid = RETAILER.id
RIGHT JOIN
(
SELECT
DRAW.retailerid
--, SUM(ISNULL(boxcount, 0)) AS boxtotal
, SUM(ISNULL(count, 0)) AS strtotal
FROM
#tbldraw AS DRAW
WHERE
ISNULL(DRAW.createddate, CAST(GETDATE() AS DATE)) = @Date
GROUP BY
DRAW.retailerid
) AS DR ON DR.retailerid = RETAILER.id
RIGHT JOIN
(
SELECT
ABACBC.retailerid
, SUM(ISNULL(abcount, 0)) AS abtotal
, SUM(ISNULL(account, 0)) AS actotal
, SUM(ISNULL(bccount, 0)) AS bctotal
FROM
#tbl_abacbc AS ABACBC
WHERE
ISNULL(ABACBC.createddate, CAST(GETDATE() AS DATE)) = @Date
GROUP BY
ABACBC.retailerid
) AS ABACBC ON ABACBC.retailerid = RETAILER.id
--GROUP BY
-- RETAILER.id, RETAILER.NAME , RETAILER.straightrate, RETAILER.boxrate, RETAILER.abcrate, RETAILER.abrate

Result :

id  retailername    atotal  Btotal  Ctotal  strtotal    abtotal actotal bctotal
1 3 Zen Commmunications 100 30 20 160 15 30 20
2 4 ASpire Systems 20 25 30 25 25 25 25


Related Topics



Leave a reply



Submit