Complex MySQL left join query - mysql

I'm trying to write more complex/better mysql statements however I'm getting a bit tripped up on using logic to create the statement and am not completely sure how to go about it. Any help is appreciated!
Basically my goal statement is to Select all from the product table, and then for every product join an image where display = 1
"SELECT p
FROM CurbbedUserBundle:Product p
LEFT JOIN CurbbedUserBundle:ProductImages i
ON p.id = i.id
WHERE i.display = 1
ORDER BY p.name ASC"
Thank you for any help!

If you want a left join, then all the conditions on the second table should be in the on clause. You need to move the condition in the where to the on:
SELECT p
FROM CurbbedUserBundle:Product p LEFT JOIN
CurbbedUserBundle:ProductImages i
ON p.id = i.id AND i.display = 1
ORDER BY p.name ASC
EDIT:
The rule for a left join is that it keeps all rows in the first table regardless of whether the on conditions is true or not. Hence, if you want to filter by the first table, put the condition in the where clause. It won't do anything in the on. The rule for right join is exactly the opposite.

Related

select records from 3 tables with same column id

I am trying to write an SQL query which will select records of a student within 3 tables that have the same column_I'd.
This is what I wrote but the the records selected are not accurate:
select
Nov_DEC_billing.*,
Nov_DEC_students_portfolio.*,
admission_form.academic_year
from
Nov_DEC_billing,
Nov_DEC_student_portfolio,
admission_form
where
Nov_DEC_billing.ID = Nov_DEC_student_portfolio.ID=admission_form.ID
AND
admission_form.Program ='Nov/dec'
I get a records selected alright but its not accurate. Please what's the right way to join 3 tables that share the same column_id.???
Use JOIN in your query
SELECT b.*, p.*, a.academic_year
FROM Nov_DEC_billing b
JOIN Nov_DEC_student_portfolio p ON p.id = b.id
JOIN admission_form a ON a.id = b.id
WHERE a.Program='Nov/dec'
You need to join tables something like this:
SELECT Nov_DEC_billing.*,
Nov_DEC_students_portfolio.*,
admission_form.academic_year
FROM Nov_DEC_billing AS ndb,
LEFT JOIN Nov_DEC_student_portfolio AS ndsp ON ndsp.ID=ndb.ID,
LEFT JOIN admission_form AS af ON af.ID=ndb.ID
WHERE af.Program='Nov/dec'
You should join all the tables to a single one.
What you will is join all the tables to a single one and then select from it.
Since you have 2 tables you should first join 2 and then join another one on the result.
See here left join example for the exact syntax.
Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID=admission_form.ID
doesn't do what you expect. It takes the first part, Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID and evaluates it. If the values match, that part becomes a 1, if they don't match, it becomes 0. Then the 0 or the 1 is compared against admission_form.ID. That is very likely to give strange results.
So you'd have to split that into:
Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID
AND Nov_DEC_student_portfolio.ID=admission_form.ID
Or just use explicit join syntax, as the others already advised (and which I do too). That forces you to split this anyway.

MYSQL join on multiple criteria not working

I have a query which uses LEFT JOIN with multiple criteria to fetch the data. However, the query does not return any data when I use more than one AND clause in the conditions.
Eg:
LEFT JOIN tblName
on x.ABC=y.ABC
AND x.MNO="AnyValue"
AND x.UserId=1
does not return any data.
However when I remove the last AND clause (i.e LEFT JOIN tblName on x.ABC=y.ABC AND x.MNO="AnyValue"), it gives me wrong result. But yes it atleast return some data.
Let me know how to add multiple conditions to get the query working.
I want to get results using the above first condition, i.e LEFT JOIN tblName on x.ABC=y.ABC AND x.MNO="AnyValue" AND x.UserId=1
Your AND ... criteria needs to be in the WHERE part of the query.
First, lets make sure you understand what a LEFT JOIN is. Try to think of it this way. The left side is how I think in the sequential order of the FROM clause. You read left-to-right, so the first table is my LEFT side which is what I ALWAYS want. The right side (next table in the query) is optional, but if it exists, great, I have more detail.
So take a scenario of people and orders. I want a list of all people. But if they have an order, thats even better.
select
P.LastName,
O.OrderID,
O.OrderDate
from
People P
LEFT JOIN Order O
on P.PersonID = O.PersonID
This will do just that. Show all people and IF they have an order, that comes along for the ride. If they have multiple orders, it will show a row for ALL orders they had.
Now, expand on criteria to the next table. Lets say I only wanted to show orders since 2018. That would become part of the LEFT JOIN "ON" clause because I only care about orders portion of the requirement.
LEFT JOIN Order O
on P.PersonID = O.PersonID
AND O.OrderDate >= '2018-01-01'
I would still get ALL people, but only order info will show for those with an order date on/after Jan 1, 2018.
Now, if you only cared about ONLY PEOPLE who HAD ORDERS AND the orders were on after 2018, that would basically eliminate the need for a LEFT JOIN and become a standard (INNER) JOIN
JOIN Order O
on P.PersonID = O.PersonID
AND O.OrderDate >= '2018-01-01'
JOIN Implies the record in the ORDER side table MUST be found
So in your scenario, where is your "x" and "y" alias name coming from. Completely unclear given the context, but hopefully the above clarification will help you resolve your query. If not, update it with more detail and clarification what you are trying to get out of it.

How to do multiple joins when some tables are empty

I am trying to append 'lookup data' to a main record text/description field so it looks something like this:
This is the Description Text
LookUpName1:
LookupValue1
LookupValueN
This worked fine with Inner Join like so
Select J.id, Concat('<b>LookUpName</b>:<br>',group_concat(F.LookUpValue SEPARATOR '<br>'))
from MainTable J Inner Join
LookUpTable L Inner Join
LookUpValuesTable F
On J.ID = L.JobID and F.ID = L.FilterID
Group by J.ID
However my goal is to add append multiple Lookup Tables and if I add them to this as Inner Joins I naturally just get those record where both/all the LookupTables have records.
On the other hand when I tried Join or Left Join I got an error on the Group by J.ID.
My goal is to append any of the existing Lookup Table values to all of the Description. Right now all I can achieve is returning appended descriptions which have ALL of the Lookup table values.
Your query would work if the on clauses were in the "right" place:
select J.id,
Concat('<b>LookUpName</b>:<br>', group_concat(F.LookUpValue separator '<br>'))
from MainTable J left join
LookUpTable L
on J.ID = L.JobID left join
LookUpValuesTable F
on F.ID = L.FilterID
group by J.ID;
The problem with your query is a MySQL (mis)feature. The on clause is optional for an inner join. Don't ask me why the MySQL designers thought inner join and cross join should be syntactically equivalent. Every other database requires an on clause for an inner join. It is easy enough to express a cross join using on 1=1.
However, the on clause is required for the left join, so when you switch to a left join, the compiler has a problem with the unorthodox syntax. The real problem is a missing on clause; this just happens to show up as "I wasn't expecting a group by yet." Using more traditional syntax with each join followed by an on should fix the problem.

Inner Join apply condition to only one table

Here is my query:
SELECT p.product_id,p.title,p.price,p.total_sales,p.total_revenue,p.timestamp,i.image_id
FROM products AS p
INNER JOIN products_images AS i
ON p.product_id = i.product_id
WHERE p.account_id = ? AND p.deleted=0 AND i.featured=1
I want to get i.image_id WHERE i.featured = 1 but I don't know how to apply that condition so that it only applies to the images table. The query works but I don't get all my results from the products table, just one row.
Obviously in some cases there might not be an image_id available where featured=1. So it would have to spit out something else in that case.
Change it to
FROM products AS p
left outer join products_images AS i
ON p.product_id = i.product_id
AND i.featured=1
WHERE p.account_id = ? AND p.deleted=0"))
Use LEFT JOIN, that way you'll get results even when there is no image. You'll get one line for every image found. If it's not desirable, use GROUP BY p.product_id to get each product just once.
And yes, put the AND i.featured=1 condition to ON statement, as #Abercrombieande mentioned.

Left outer join and sum issue

I need a query. I'm trying to sum of one field with joined tables. Some records not in second table. So this records sum should be zero. But the query only sum the records which are in the second table.
select s.*,sum(sd.fiyat) as konak from fuar_sozlesme1 s
left outer join fuar_sozlesme1_detay sd on (sd.sozlesme_id = s.id)
------EDIT-------
I added group by into the query and solved my problem. Here is the new ;
select s.*,sum(sd.fiyat) as konak from fuar_sozlesme1 s
left outer join fuar_sozlesme1_detay sd on (sd.sozlesme_id = s.id)
group by sd.sozlesme_id
I thinik you need to use IFNULL(sd.fiyat,0) instead of sd.fiyat to get zeros for the NULL values coming from the second table because of the LEFT JOIN like so:
SELECT s.*, SUM(IFNULL(sd.fiyat, 0)) as konak
FROM fuar_sozlesme1 s
LEFT OUTER JOIN fuar_sozlesme1_detay sd ON sd.sozlesme_id = s.id
GROUP BY s.someFields
Here is a simple example, you may help: http://sqlfiddle.com/#!2/41481/1
This is an old thread, but I spent a couple of hours trying to solve the same issue.
My query has two joins, a filter and a SUM function. I'm no SQL expert, but this helped me achieve the desired result of still showing a result even if the joined table had no rows to sum.
The key for me in order to show results even if the sum was totaling nothing, was the GROUP BY. I'm still not 100% sure why.
The two types of joins were chosen based on this article - MySQL Multiple Joins in one query?
SELECT registrations.reg_active, registrations.team_id, registrations.area_id, registrations.option_id, registrations.reg_fund_goal, registrations.reg_type, registrations.reg_fee_paid, registrations.reg_has_avatar, users.user_name, users.user_email, users.user_phone, users.user_zip, users.user_age, users.user_gender, users.user_active, SUM(IFNULL(donations.donation_amount,0)) as amt from registrations
INNER JOIN `users`
ON registrations.user_id = users.user_id
AND registrations.event_id = :event_id
LEFT OUTER JOIN `donations`
ON registrations.reg_id = donations.reg_id
GROUP BY donations.reg_id
ORDER BY users.user_name ASC