Multiple LEFT JOINS on the same table, using data from previous JOIN - mysql

I am using a LEFT JOIN in mysql to look up an organisation from a code which is in my dataset.
So the datatable might contain the orgcode 123
Then the orgtable contains the orgname of the organisation ie 'The Local Bookstore'.
However the orgtable also contains another code which identifies the parent organisation of the 'The Local Bookstore', using another code ie 456.
How do I write a query that goes to the orgtable, looks up the orgname, also finds the parentorgcode and then looks that up in the same table to find the parent organisation name as well?
Basically using the output of one LEFT JOIN to generate another LEFT JOIN in the same query...
Thanks

First things first, if you are managing a hierarchy of data I highly recommend reading http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ as it will show you various methods to store it which may well allow you to use a more optimal method than you currently are.
Secondly, you can LEFT JOIN easily enough as you have asked but just need to make sure each new join uses an alias so that there is no ambiguity as to which field you request, i.e.
SELECT
*
FROM datatable AS d
LEFT JOIN orgtable AS o1 ON o1.orgID = d.orgID
LEFT JOIN orgtable AS o2 ON o2.orgID = o1.parentOrgID
What you cannot do is automatically make MySQL keep adding on LEFT JOIN's until there is no parent. For that you will need either a recursive stored procedure, a looping stored procedure, or a nested tree (see link)

try to use alias like this:
SELECT tb1.orgcode, tb2.orgcode
FROM orgtable AS tb1 LEFT OUTER JOIN orgtable AS tb2 ON tb1.orgcode = tb2.orgcode

SELECT O1.NAME AS ORG_NAME, O2.NAME AS PARENT_ORG_NAME
FROM DATATABLE D
JOIN ORGANISTION O1
ON D.ORGID = O1.ORG_ID
LEFT JOIN ORGANISTION O2
ON O1.PARENT_ID = O2.ID

Related

MySQL - Why does WHERE ignore RIGHT JOIN?

I have the following MySQL query:
SELECT inv.inventory_id, inv.item_id, item.description, inv.quantity, item.class_id, class.description AS class,
class.is_spool, inv.location_id, location.description AS location, location.division_id, division.name AS division,
inv.service_date, inv.reel_number, inv.original_length, inv.current_length, inv.outside_sequential,
inv.inside_sequential, inv.next_sequential, inv.notes, inv.last_modified, inv.modified_by
FROM reel_inventory AS inv
INNER JOIN reel_items AS item ON inv.item_id = item.item_id
INNER JOIN reel_locations AS location ON inv.location_id = location.location_id
INNER JOIN locations AS division ON location.division_id = division.location_id
RIGHT JOIN reel_classes AS class on item.class_id = class.class_id;
The query works exactly as expected as is. What I was trying to do was add a WHERE clause to this query with one qualifier. For example:
RIGHT JOIN reel_classes AS class ON item.class_id = class.class_id
WHERE inv.current_length > 0;
When I do this, all of the results from the RIGHT JOIN are not included in the result. I've not had a ton of experience with advanced queries, but could someone explain why the RIGHT JOIN is excluded from the result set when a WHERE is used, and how to property write the query to include the RIGHT JOIN information?
Thanks in advance.
What you want is:
RIGHT JOIN reel_classes AS class
ON item.class_id = class.class_id AND
inv.current_length > 0;
Your question is why the RIGHT JOIN turns into an INNER JOIN with the WHERE clause.
The reason is simple. For the non-matching rows, inv.current_length is NULL and this fails the comparison.
I would also suggest that you use LEFT JOIN, starting with the table where you want to keep all the rows. Most people find it much easier to understand logic that is "keep all rows in the first table" rather than "keep all rows in some table whose name will come up".

Replace the id's with name using single query

SELECT team_with.participant1,team_with.participant2,team_with.participant3
FROM event,team_with
WHERE team_with.for_event_no=event.event_no AND
event.event_no=4 AND
team_with.participant1=9 OR
team_with.participant2=9 OR
team_with.participant3=9;
I have written the particular query, and obtained the required id's in a row. I am not able to modify this query such that, in place of these id's, names connected to the id's are displayed.
The student_detatil table consists of PK(sam_id) and the attribute name.
IDs displayed by the present query are FKs connected to student_detail.sam_id..
It seems like a bad design to multiply columns storing different participants. Consider creating a separate row for each participant and storing them in a table. Your joining logic would also be easier.
Also, please use explicit JOIN syntax - it makes the query clearer and easier to understand by separating join logic with conditions for data retrieval.
Remember that operator AND has a precedence over OR, so that your event.event_no = 4 does not apply to each participant condition. I believe this was a mistake, but you are the one to judge.
As to the query itself, you could apply OR conditions into join, or simply join the student_detail table thrice.
SELECT
s1.name,
s2.name,
s3.name
FROM
event e
INNER JOIN team_with t ON t.for_event_no = e.event_no
LEFT JOIN student_detail s1 ON s1.sam_id = t.participant1
LEFT JOIN student_detail s2 ON s2.sam_id = t.participant2
LEFT JOIN student_detail s3 ON s3.sam_id = t.participant3
WHERE
e.event_no = 4
AND ( t.participant1=9 OR t.participant2=9 OR t.participant3=9 );

MySQL Sub-Query or LEFT JOIN for SELECTing missing columns?

I need to perform a SELECT query on 3 tables and i don't know if using a sub-query could be better than a LEFT JOIN since one column in some case might be missing. These are the tables:
Options (name, info...)
Owners (name, address)
Rel (idoption, idowner)
The SELECT should return all the Options with the name of the Owner inside each record but, in some case, the Option might not be connected to any Owner and the name of the Owner should be empty.
Any suggestions? Thanks in advance
A LEFT JOIN is likely the appropriate response and will probably be faster than a subquery depending on your results (it's possible that they'd compile to the same plan).
SELECT
op.name
,op.info
,...
,ow.name
,ow.address
FROM
options op
LEFT OUTER JOIN
Rel r
ON r.idoption = op.id
LEFT OUTER JOIN
owners ow
ON ow.id = r.idowner
LEFT JOIN then, it will get all the Options irregardless if there is a matching Owner or not - "This extra consideration to the left table can be thought of as special kind of preservation. Each item in the left table will show up in a MySQL result, even if there isn't a match with the other table that it is being joined to."
from: http://www.tizag.com/mysqlTutorial/mysqlleftjoin.php
A left join will be much more efficient and faster than a subquery. If you can live with NULLs for the cases where there's no match, it's the better approach.

MySQL left join with multiple views

I have the following query, which I designed to compile data from a number of views based on client data.
SELECT
vw_clients.client_id,
name,
exts,
vms,
ivrs,
queues,
conf10,
conf20,
conf30
FROM
vw_clients,
vw_exts,
vw_vms,
vw_ivrs,
vw_queues,
vw_conf10,
vw_conf20,
vw_conf30
WHERE
vw_clients.client_id = vw_exts.client_id AND
vw_clients.client_id = vw_vms.client_id AND
vw_clients.client_id = vw_ivrs.client_id AND
vw_clients.client_id = vw_queues.client_id AND
vw_clients.client_id = vw_conf10.client_id AND
vw_clients.client_id = vw_conf20.client_id AND
vw_clients.client_id = vw_conf30.client_id;
The query works fine so long as there are records in every view relating to the records in vw_clients. However I need to modify this to use a left join, so that it returns all records from vm_clients and only those from the other views that have records for those clients.
I've read about left joins, but at most I have only found info on joining one or maybe two tables - but I need to join 8. Do I do a left join on vw_clients.client_id to the corresponding client_id field in all of the views? What's the syntax for that?
Would be grateful for any help. I'm very close to solving this issue and I think this is the last piece of the puzzle!
Many thanks.
You can use left join by putting vw_clients in the first in the from list, then all other tables followed after left join. The left join can join only two tables or one "result set" and a table,where the result set is the result of the former join.
In your case:
SELECT
T0.client_id, name, exts, vms, ivrs, queues, conf10, conf20, conf30
FROM
vw_clients T0
left join vw_exts T1 on T0.client_Id=T1.client_id
Left join vw_vms T2 on ...
...
Where ...
Maybe here you don't need where clause.
Yes, you’d just replace your WHERE with a LEFT JOIN.
LEFT JOIN vw_exts ON vw_clients.client_id = vw_exts.client_id
Then you can remove those extra tables from the FROM part.

How do I decide when to use right joins/left joins or inner joins Or how to determine which table is on which side?

I know the usage of joins, but sometimes I come across such a situation when I am not able to decide which join will be suitable, a left or right.
Here is the query where I am stuck.
SELECT count(ImageId) as [IndividualRemaining],
userMaster.empName AS ID#,
CONVERT(DATETIME, folderDetails.folderName, 101) AS FolderDate,
batchDetails.batchName AS Batch#,
Client=#ClientName,
TotalInloaded = IsNull(#TotalInloaded,0),
PendingUnassigned = #PendingUnassigned,
InloadedAssigned = IsNull(#TotalAssigned,0),
TotalProcessed = #TotalProcessed,
Remaining = #Remaining
FROM
batchDetails
Left JOIN folderDetails ON batchDetails.folderId = folderDetails.folderId
Left JOIN imageDetails ON batchDetails.batchId = imageDetails.batchId
Left JOIN userMaster ON imageDetails.assignedToUser = userMaster.userId
WHERE folderDetails.ClientId =#ClientID and verifyflag='n'
and folderDetails.FolderName IN (SELECT convert(VARCHAR,Value) FROM dbo.Split(#Output,','))
and userMaster.empName <> 'unused'
GROUP BY userMaster.empName, folderDetails.folderName, batchDetails.batchName
Order BY folderDetails.Foldername asc
Yes, it depends on the situation you are in.
Why use SQL JOIN?
Answer: Use the SQL JOIN whenever multiple tables must be accessed through an SQL SELECT statement and no results should be returned if there is not a match between the JOINed tables.
Reading this original article on The Code Project will help you a lot: Visual Representation of SQL Joins.
Also check this post: SQL SERVER – Better Performance – LEFT JOIN or NOT IN?.
Find original one at: Difference between JOIN and OUTER JOIN in MySQL.
In two sets:
Use a full outer join when you want all the results from both sets.
Use an inner join when you want only the results that appear in both
sets.
Use a left outer join when you want all the results from set a, but
if set b has data relevant to some of set a's records, then you also
want to use that data in the same query too.
Please refer to the following image:
I think what you're looking for is to do a LEFT JOIN starting from the main-table to return all records from the main table regardless if they have valid data in the joined ones (as indicated by the top left 2 circles in the graphic)
JOIN's happen in succession, so if you have 4 tables to join, and you always want all the records from your main table, you need to continue LEFT JOIN throughout, for example:
SELECT * FROM main_table
LEFT JOIN sub_table ON main_table.ID = sub_table.main_table_ID
LEFT JOIN sub_sub_table on main_table.ID = sub_sub_table.main_table_ID
If you INNER JOIN the sub_sub_table, it will immediately shrink your result set down even if you did a LEFT JOIN on the sub_table.
Remember, when doing LEFT JOIN, you need to account for NULL values being returned. Because if no record can be joined with the main_table, a LEFT JOIN forces that field to appear regardless and will contain a NULL. INNER JOIN will obviously just "throw away" the row instead because there's no valid link between the two (no corresponding record based on the ID's you've joined)
However, you mention you have a where statement that filters out the rows you're looking for, so your question on the JOIN's are null & void because that is not your real problem. (This is if I understand your comments correctly)