MySQL Multiple Table Joins incorrect summation - mysql

I'm trying to join and sum three tables together (MySQL), grouped by a 'tracking number' and an 'order_ID':
invoice_data_dhl
master_track_nums
payments
Problem: When they are multiple payments rows for an order_ID, it is multiplying the DHL_COST total by the number of results in the payments table for the order_ID.
SELECT
invoice_data_dhl.Waybill_Number,
sum(invoice_data_dhl.AWB_Original_Amount) AS DHL_COST,
master_track_nums.order_ID,
sum(payments.revenue) AS REVENUE
FROM invoice_data_dhl
LEFT JOIN master_track_nums
ON invoice_data_dhl.Waybill_Number = master_track_nums.track
LEFT JOIN payments
ON master_track_nums.order_ID = payments.order_ID
GROUP BY invoice_data_dhl.Waybill_Number
Can this be written so that I can get the results with a single query that outputs the results like the below?
Waybill_Number DHL_COST order_ID REVENUE
7022193792 182.52 110632 234
4536137201 3311.96 107637 4074
3927382187 248.95 110384 636
7812896712 74.85 106998 247
Thanks for any help in advance!

UNTESTED: but something like this: Updated: didn't remove sum on revenue in inline query.
SELECT A.waybill_number, A.DHL_COST, A.Order_ID, Sum(payments.Revenue)
FROM
(SELECT invoice_data_dhl.Waybill_Number,
sum(invoice_data_dhl.AWB_Original_Amount) AS DHL_COST,
master_track_nums.order_ID
FROM invoice_data_dhl
LEFT JOIN master_track_nums
ON invoice_data_dhl.Waybill_Number = master_track_nums.track
GROUP BY master_track_nums.Order_ID, invoice_data_dhl.Waybill_Number) A
LEFT JOIN payments
ON A.order_ID = payments.order_ID
GROUP BY A.waybill_number, A.DHL_COST, A.Order_ID

Related

SQL Sum and Groupby Statement return wrong/weird number

Let's get to the point:
My first query:
select hotel, sum(adult) from bookings
group by hotel;
and it shows the correct sum number, but whenever I try to join with other table:
select b.hotel, avg(r.hotelfacilities) as FacilitiesScore,
avg(r.hotelservice) as ServiceScore,
avg(r.hotelroom) as RoomScore,
avg(b.rate) as PriceScore,
sum(b.adult) as Persons
from bookings b join reviews r
on b.id = r.booking_id
group by b.hotel;
the number is weird and a lot bigger than it should be. Where did I do wrong?
select b.hotel,
avg(r.hotelfacilities) as FacilitiesScore,
avg(r.hotelservice) as ServiceScore,
avg(r.hotelroom) as RoomScore,
avg(b.rate) as PriceScore,
sum(b.adult) as Persons
from bookings b join reviews r
group by b.hotel
on b.id = r.booking_id;

MySql sum DISTINCT after join

I have 2 table that join together ( Orders and Order_item)
When I use join I get duplicates records then I eliminate them with DISTINCT, but when I want to get sum the the shipping_price DISTINCT not works because it just eliminate the same price value and I all my prices are same I get 1 not sum !
If I don't use DISTINCT , I get rows per each items in order
SELECT sum(DISTINCT shipping_price) FROM `product_order`
INNER JOIN `product_address`
ON `product_order`.`address_id` = `product_address`.`id`
INNER JOIN `product_item`
ON `product_order`.`id` = `product_item`.`order_id`
WHERE (`status`<>2)
AND (`company_id`=1968)
AND DATE(date)='2021-08-31'
ORDER BY `product_order`.`id` DESC
how to get sum of shipping price correctly ..
data in order_table is
id shipping_price status
100
200
200
100
sum = 600 , but how to get it, if I did't DISTINCT, I get more than one row per order_items row counts that join tho order..
Use a subquery to get your shipping prices. Something like this:
SELECT product_order.id,
SUM(product_item.price * product_item.quantity) shipping_price
FROM product_order
JOIN product_item ON product_order.id = product_item.order_id
GROUP BY product_order.id
The trick here is to get a subquery that delivers exactly one row per order, with the summed-up shipping priced in it. Do your SUM() ... GROUP BY ...` in the subquery. That way you'll avoid any duplication of items.
TEST THIS before you proceed to make sure it works: giving each order id and its shipping price.
Then use it as if it were a table, JOINing it to the rest.
SELECT total.shipping_price,
product_order.id,
product_address.*
FROM product_order
JOIN product_address
ON product_order.id = product_address.order_id
JOIN (
SELECT product_order.id,
SUM(product_item.price * product_item.quantity) shipping_price
FROM product_order
JOIN product_item ON product_order.id = product_item.order_id
GROUP BY product_order.id
) total ON product_order.id = total.id
ORDER BY product_order.id = total.id
Use a subquery instead of a join.
SELECT (
select sum(shipping_price)
FROM product_item
WHERE po.`id` = `product_item`.`order_id`
) as shipping_price
FROM `product_order` po
INNER JOIN `product_address`
ON `product_order`.`address_id` = `product_address`.`id`
WHERE (`status`<>2)
AND (`company_id`=1968)
AND DATE(date)='2021-08-31'
ORDER BY `product_order`.`id` DESC

SQL Using count and sum when joining 3 tables

When I try to join 2 tables and use SUM or COUNT it all works perfectly and as expected. However when I join 3 tables SUM and COUNT makes no sense because the JOIN statements create extra rows for each table to have a unique row so they over count and over sum the required values.
Here is the query:
SELECT PO_club.clubid, PO_club.name, PO_club.pic, PO_club.points, count(PO_club_user.userid), SUM(PO_club_point_log.points)
FROM PO_club
INNER JOIN PO_club_user ON PO_club.clubid = PO_club_user.clubid
LEFT JOIN PO_club_point_log ON PO_club.clubid = PO_club_point_log.clubid
WHERE PO_club.deleted = 0
GROUP BY PO_club.clubid
ORDER BY PO_club.points DESC;
If I run two separate scripts like first join only PO_club and PO_club_user to get COUNT() it works. And then run PO_club JOIN PO_club_point_log to get SUM() its all good. However, I need to run it one script so that i would not need to sort it at the front end. Is there a way to join 3 tables and somehow COUNT() just work on PO_club and PO_club_users while SUM only on PO_club and PO_club_point_log?
Thanks!
How's this? This will include all PO_clubs even if they don't have any users in case they have points. If that's not what you want, change the first LEFT JOIN to INNER JOIN.
SELECT PO_club.clubid, PO_club.name, PO_club.pic, PO_club.points, count(PO_club_user.userid), t.sum_points
FROM PO_club
LEFT JOIN PO_club_user ON PO_club.clubid = PO_club_user.clubid
LEFT JOIN
(SELECT PO_club_point_log.clubid, SUM(PO_club_point_log.points) AS sum_points
FROM PO_club_point_log INNER JOIN PO_club ON PO_club_point_log.clubid = PO_club.clubid
GROUP BY PO_club_point_log.clubid) AS t
ON PO_club.clubid = t.clubid
WHERE PO_club.deleted = 0
GROUP BY PO_club.clubid
ORDER BY PO_club.points DESC

How to minimize time in mySQL select query?

I have this query wherein I want to find out the sales for the current year and the sales for last year. I cannot make it into 2 separate queries since it has to be of the same item code. Meaning the item codes used in the sales for the current year must also be the item codes used for the sales last year.
The code below is working but it takes almost 8 to 9 minutes to fetch
select p.itemcode,
p.itemdescription,
( select round((SUM(SA.QUANTITY*P.SellingPrice)),2)
from sales s
join product p on s.itemcode=p.itemcode
where YEAR(s.date) = 2013
),
( select round((SUM(SA.QUANTITY * P.SellingPrice)),2)
from sales s
join product p on s.itemcode=p.itemcode
where YEAR(s.date) = 2012
)
from product p
join supplier s on p.suppliercode = s.suppliercode
join currency c on c.countrycode=s.countrycode
join country co on co.countrycode=c.countrycode
JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where c.countrycode = 'NZ'
group by p.itemcode
limit 10
Ideally the output should be
Itemcode Itemdescription SalesforCurrentYear SalesforLastYear
GS771516 BUBBLE PARTY MACHINE 1035300.00 2079300.00
GSNBC-025 X'MAS HOUSE 600612.25 1397163.25
GSNBC-031 BRANDENBURGER TOR 741010.75 1572207.25
Thanks!!
The query can be simplified by eliminating two joins:
select .......
.......
from product p
join supplier s on p.suppliercode = s.suppliercode
JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where s.countrycode = 'NZ'
group by p.itemcode
limit 10
Afterwards, two dependent subqueries in the select clause can be reduced to one outer join:
select p.itemcode,
p.itemdescription,
round((SUM( CASE WHEN YEAR(s.date) = 2013
THEN SA.QUANTITY*P.SellingPrice
ELSE 0 END
)),2) As Sum2013,
round((SUM( CASE WHEN YEAR(s.date) = 2012
THEN SA.QUANTITY * P.SellingPrice
ELSE 0 END
)),2) As Sum2012
from product p
join supplier s on p.suppliercode = s.suppliercode
LEFT JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where s.countrycode = 'NZ'
group by p.itemcode
limit 10
Please try this query and let us know how it will perform.
Follow any of these steps
1.You can parse your query.
2.Remove redundant statements.
3.Use inner join or outer join.
You've got sales three times in the same scope. I'd get rid of two of those, and that should help. Also, in terms of business logic, all of these tables seem mandatory for a sale. If that's true, you should use "inner join", for compatibility with standard SQL - even though it's the same in MySQL.

Adding one JOIN statement changes the value of precedent sum

I have this query in sqlfiddle which gives the correct values
But when I add one left joined table the result changes(I tried with right and inner join same bad result) and it's there in this sqlfiddle
What I miss in this query when adding stockdata?
There is 3 tables defmatiere, ingredients and stockdata
When I use this query:
SELECT dm.nom,SUM(IF(dm.id=ig.matid AND ig.matcuisine= 3,ig.qty,0)) AS bisused
FROM ingredient AS ig
LEFT JOIN DefMatiere AS dm ON ig.matid=dm.id AND ig.matcuisine=3
WHERE dm.id=ig.matid AND dm.type=1 GROUP BY dm.nom
I get the corrects sums
But When I use this query
SELECT dm.nom,SUM(IF(dm.id=ig.matid AND ig.matcuisine= 3,ig.qty,0)) AS bisused,
SUM(DISTINCT IF(dm.id=sd.matid, sd.quantite,0)) AS bisbought
FROM ingredient AS ig
LEFT JOIN DefMatiere AS dm ON ig.matid=dm.id AND ig.matcuisine=3
LEFT JOIN StockData AS sd ON sd.matid=dm.id
WHERE dm.id=ig.matid AND dm.type=1 GROUP BY dm.nom
The sum of bisused is doubled the rest is correct