Adding one JOIN statement changes the value of precedent sum - mysql

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

Related

SQL - order by is breaking my query when there is no reviews

I have the rather lengthy SQL query that I have included below. As you can see it orders by AvgRating and NumReviews, both of which rely on data from the reviews table. Unfortunately I need to see the rows in my results even when there are no reviews, currently if there are no reviews to order by then that row just doesnt show up in the results. All help greatly appreciated.
SELECT travisor_tradesperson.name, travisor_tradesperson.id, travisor_catagory.catname,
travisor_company.cname, travisor_company.description, travisor_company.city, travisor_company.address, travisor_company.postcode, travisor_company.phone,
ROUND(AVG(travisor_review.rating)) as RoundAvgRating, AVG(travisor_review.rating) as AvgRating, COUNT(travisor_review.rating) as NumReviews
FROM `travisor_tradesperson`
INNER JOIN travisor_company
ON travisor_tradesperson.company = travisor_company.id
INNER JOIN travisor_catagory
ON travisor_tradesperson.catagory = travisor_catagory.id
INNER JOIN travisor_review
ON travisor_review.tradesperson = travisor_tradesperson.id
WHERE travisor_catagory.catname = '$catagory'
AND travisor_company.city = '$city'
GROUP BY travisor_tradesperson.name, travisor_catagory.catname, travisor_company.cname,
travisor_company.description
ORDER BY AvgRating DESC, NumReviews DESC
Left join travisor_review instead of Inner Join. Inner join will only find records that are present in both tables. If you have no reviews for that tradesperson record, it will drop from the results set.
Left join will return a NULL if it cannot match on the join predicate. In this case, the tradesperson will return but with a NULL. Convert the NULL to a 0 if needed and that should fix your AVG.

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

Query with joins

I am running a query:
select course.course,iars.id,
students.rollno,
students.name as name,
teachers.name as tname,
students.studentid,
attndata.studentid ,sum(attndata.obt) as obt
sum(attndata.benefits) as ben , (sum(attndata.max)) as abc
from groups, students
left join iars
on iars.id
left join str
on str.studentid=students.studentid
left join course
on course.c_id=students.course
left join teachers
on teachers.id=iars.teacherid
join sgm
on sgm.studentid=students.studentid
left join attndata
on attndata.studentid=students.studentid and iars.id=attndata.iarsid
left join sps
on sps.studentid=students.studentid and iars.paperid=sps.paperid
left join semdef
on semdef.semesterid=str.semesterid
where students.course='1'
and students.status='regular'
and sps.paperid='5'
and iars.courseid=students.course
and iars.semester=str.semesterid
and semdef.month=9
and iars.paperid='5'
and str.semesterid='1'
and str.sessionid='12'
and groups.id=sgm.groupid
group by sps.studentid,
teachers.id,
semdef.month
order by
students.name
In this query whenever I am having left join on semdef.id=attndata.mon, I am getting zero result when the value of semdef.id=null but I want all the results, irrespective of semdef, but I want to use it. As in it should fetch result, if the values are null. Can you please help it out.
It's probably because your where clause is saying
and semdef.month=9
and you probably want
and (semdef.month=9 OR semdef.id IS NULL)
or something similar.
It's because your where clause has statements relating to the semdef table. Add these to the join clause as putting these in the where is implying an inner join.
Eg:
Left join semdef on xxx and semdef.id = attndata.min

mySQL union allow for non match

I am trying to write a query that will pull some product information AND photos, if the product has any.
select
prod.pID, prod.Manufacturer_Name, prod.pUPC, prod.pNum, prod.pPrice, prod.pSalesPrice, prod.pSalesDate, prod.pSalesEndDate, prod.pSale,
GROUP_CONCAT(photoName) as photos
from
ds_products as prod
inner join ds_photos as pics on pics.objectID=prod.pID
where
pics.photoFlag =2
group by
prod.pID
The problem with this is that products that do not have photos get left out of the result set. What do I need to add and/or change to allow for a product that doesn't appear in the photos table to show up in the results?
Thanks
EDIT
I tried the LEFT JOIN instead of inner but get the same result set. If i run just:
select
prod.pID, prod.Manufacturer_Name, prod.pUPC, prod.pNum, prod.pPrice, prod.pSalesPrice, prod.pSalesDate, prod.pSalesEndDate, prod.pSale
from
ds_products as prod
I get about 600k results. The inner and or left join queries get about 190k results. Is there another way to do this?
Use outer join
select
prod.pID, prod.Manufacturer_Name, prod.pUPC, prod.pNum, prod.pPrice, prod.pSalesPrice, prod.pSalesDate, prod.pSalesEndDate, prod.pSale,
GROUP_CONCAT(photoName) as photos
from
ds_products as prod
LEFT join ds_photos as pics on pics.objectID=prod.pID
where
pics.photoFlag =2 OR pics.photoFlag is NULL
group by
prod.pID
I have added a condition which check if photoFlag is null for the products which don't have corresponding pics
Here is working fiddle : http://sqlfiddle.com/#!2/c2a9c/1/0
For more information: http://dev.mysql.com/doc/refman/5.0/en/outer-join-simplification.html
You need to use a LEFT JOIN instead of INNER JOIN like this
select
prod.pID, prod.Manufacturer_Name, prod.pUPC, prod.pNum, prod.pPrice, prod.pSalesPrice, prod.pSalesDate, prod.pSalesEndDate, prod.pSale,
GROUP_CONCAT(photoName) as photos
from
ds_products as prod
LEFT JOIN ds_photos as pics on pics.objectID=prod.pID
group by
prod.pID
Note I have also removed your where clause, as this was looking for a value in pics table that would restrict the result set.

MySql Query takes forever

hi I am doing A query to get some product info, but there is something strange going on, the first query returns resultset fast (.1272s) but the second (note that I just added 1 column) takes forever to complete (28-35s), anyone know what is happening?
query 1
SELECT
p.partnumberp,
p.model,
p.descriptionsmall,
p.brandname,
sum(remainderint) stockint
from
inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid= ind.inventoryinid)
group by partnumberp, projectid
query 2
SELECT
p.partnumberp,
p.model,
p.descriptionsmall,
p.brandname,
p.descriptiondetail,
sum(remainderint) stockint
from
inventario_dbo.inventoryindetails inda
left join purchaseorders.product p on (p.partnumberp = inda.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid= inda.inventoryinid)
group by partnumberp, projectid
You shouldn't group by some columns and then select other columns unless you use aggregate functions. Only p.partnumberp and sum(remainderint) make sense here. You're doing a huge join and select and then the results for most rows just end up getting discarded.
You can make the query much faster by doing an inner select first and then joining that to the remaining tables to get your final result for the last few columns.
The inner select should look something like this:
select p.partnumberp, projectid, sum(remainderint) stockint
from inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid = ind.inventoryinid)
group by partnumberp, projectid
After the join:
select T1.partnumberp, T1.projectid, p2.model, p2.descriptionsmall, p2.brandname, T1.stockint
from
(select p.partnumberp, projectid, sum(remainderint) stockint
from inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid = ind.inventoryinid)
group by partnumberp, projectid) T1
left join purchaseorders.product p2 on (p2.partnumberp = T1.partnumberp)
Is descriptiondetail a really large column? Sounds like it could be a lot of text compared to the other fields based on its name, so maybe it just takes a lot more time to read from disk, but if you could post the schema detail for the purchaseorders.product table or maybe the average length of that column that would help.
Otherswise I would try running the query a few times and see you consistently get the same time results. Could just be load on the database server the time you got the slower result.