Multiple join in mysql - sql

I am trying to do a multiple join like this
SELECT * FROM (((Customer FULL JOIN Booking ON Customer.ID = Booking.CustID)
FULL JOIN Flight ON Booking.FlightID = Flight.ID)
FULL JOIN FlightRoute ON Flight.RouteID = FlightRoute.ID)
But it is syntactically incorrect according to mysql. Please help

There is no FULL JOIN in MySQL. It's convoluted but a FULL JOIN is equivalent to a UNION ALL between a LEFT JOIN and a RIGHT JOIN, using a condition to remove duplicates. It's late in the day and the thought of your 3 FULL JOINs in that statement is hurting my head.
You do say in Conrad Frix's answer that removing the FULL makes it work, if it does then you have misunderstood how FULL JOINs and INNER JOINs work.
For the first FULL JOIN it would look like:
SELECT * FROM Customers c
LEFT JOIN Booking b ON c.ID = b.CustId
UNION ALL
SELECT * FROM Customers c
RIGHT JOIN Booking b ON c.ID = b.CustId
WHERE c.ID IS NULL
Use that basis to form the rest of your statements.

When i was looking about MySql and FULL Join i found this article which explains a number of ways to emulate FULL JOIN in Mysql. I think it could be usefull to you.
How to simulate FULL OUTER JOIN in MySQL

MySQL isn't my area of expertises but I don't think MySQL supports full joins. I found a simple article that details some alternatives.
http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/

Related

How to build a complex sql query?

Database design here
I want to get records from the product_spec_data table that are associated with products whose category_id is 5.
Please help me make a query to the database...
All of the relationship are clearly laid out, a simple join across tables would works.
SELECT psd.*
FROM product_spec_data psd
INNER JOIN product_spec_values psv ON psd.id = psv.product_spec_data_id
INNER JOIN products prod ON psv.product_id = prod.id
INNER JOIN categories cat ON prod.category_id = cat.id
-- with category id = 5
WHERE cat.id = 5;
I am not sure what do you mean by complex query. I guess your question is not complete. I think the query for your question (if it is T-SQL) will be as follows
select d.*
from product_spec_data d
left outer join product_spec_values v on d.id=v.product_spec_data_id
left outer join products p on v.product_id=p.id
where p.category_id=5
(I think in MySQL also above syntax will remain same, you may remove [outer] clause in MySQL)

How to join three tables in sql server

I have three tables:
Chapter (ChapterNo, Desc)
Lesson (LessonNO, Dec, ChapterNo)
Case (CaseNo, Desc, LessonNo)
As you see, the three tables are all connected. What I want is to return all the chapters (even without lessons in it), all the lessons (even without cases in it) and all the cases.
I am sorry to say but I really don't have an idea so I have no sample code. I hope my explanations are enough.
USE LEFT JOIN:
SELECT
C.*,
L.*,
CA.*
FROM Chapter C
LEFT JOIN Lesson L ON C.ChapterNo=L.ChapterNo
LEFT JOIN Case CA ON L.LessonNo=CA.LessonNo
Use Left Join query in order to get your desired result
As for naming of tables. Don't use Case as table name because it is a reserved word for SQL.
SELECT CH.ChapterNo,CH.Desc,LE.LessonNo,LE.Dec,CA.CaseNo,CA.Desc FROM Chapter CH
LEFT JOIN Lesson LE ON CH.ChapterNo = LE.ChapterNo LEFT JOIN Cases CA ON LE.LessonNo = CA.LessonNO
SELECT *
FROM Chapter C
LEFT JOIN Lesson L ON C.ChapterNo=L.ChapterNo
LEFT JOIN Case CA ON L.LessonNo=CA.LessonNo
Select * From Chapter c
Left Join Lesson l On c.ChapterNo=l.ChapterNo
Left Join Case cs On cs.LessonNo=l. LessonNo

SQL - Consecutive "ON" Statements

As I was cleaning up some issues in an old view in our database I came across this "strange" join condition:
from
tblEmails [e]
join tblPersonEmails [pe]
on (e.EmailID = pe.EmailID)
right outer join tblUserAccounts [ua]
join People [p]
on (ua.PersonID = p.Id)
join tblChainEmployees [ce]
on (ua.PersonID = ce.PersonID)
on (pe.PersonID = p.Id)
Table tblUserAccounts is referenced as a right outer join, but the on condition for it is not declared until after tblChainEmployees is referenced; then there are two consecutive on statements in a row.
I couldn't find a relevant answer anywhere on the Internet, because I didn't know what this kind of join is called.
So the questions:
Does this kind of "deferred conditional" join have a name?
How can this be rewritten to produce the same result set where the on statements are not consecutive?
Maybe this is a "clever" solution when there has always been a simpler/clearer way?
(1) This is just syntax and I've never heard of some special name. If you read carefully this MSDN article you'll see that (LEFT|RIGHT) JOIN has to be paired with ON statement. If it's not, expression inside is parsed as <table_source>. You can put parentheses to make it more readable:
from
tblEmails [e]
join tblPersonEmails [pe]
on (e.EmailID = pe.EmailID)
right outer join
(
tblUserAccounts [ua]
join People [p]
on (ua.PersonID = p.Id)
join tblChainEmployees [ce]
on (ua.PersonID = ce.PersonID)
) on (pe.PersonID = p.Id)
(2) I would prefer LEFT syntax, with explicit parentheses (I know, it's a matter of taste). This produces the same execution plan:
FROM tblUserAccounts ua
JOIN People p ON ua.PersonID = p.Id
JOIN tblChainEmployees ce ON ua.PersonID = ce.PersonID
LEFT JOIN
(
tblEmails e
JOIN tblPersonEmails pe ON e.EmailID = pe.EmailID
) ON pe.PersonID = p.Id
(3) Yes, it's clever, just like some C++ expressions (i.e. (i++)*(*t)[0]<<p->a) on interviews. Language is flexible. Expressions and queries can be tricky, but some 'arrangements' lead to readability degradation and errors.
Looks to me like you have tblEmail and tblPerson with their own independent IDs, emailID and ID (person), a linking table tblPersonEmail with the valid pairs of emailID/IDs, and then the person table may have a 1-1 relationship with UserAccount, which may then have a 1-1 relationship with chainEmployee, so to get rid of the RIGHT OUTER JOIN in favor of LEFT, I'd use:
FROM
((tblPerson AS p INNER JOIN
(tblEmail AS e INNER JOIN
tblPersonEmail AS pe ON
e.emailID = pe.emailID) ON
p.ID = pe.personID) LEFT JOIN
tblUserAccount AS ua ON
p.ID = ua.personID) LEFT JOIN
tblChainEmployee AS ce ON
ua.personID = ce.personID
I can't think of a great practical example of this off the top of my head so I'll give you a generic example that hopefully makes sense. Unfortunately I'm not aware of a generic name for this either.
Many people will start off with a query like this:
select ...
from
A a left outer join
B b on b.id = a.id left outer join
C c on c.id2 = b.id2;
The look at the results and realize that they really need to eliminate the rows in B that don't have a corresponding C but if you tried to say where b.id2 is not null and c.id2 is not null you've defeated the whole purpose of the left join from A.
So next you try to do this but it doesn't take long to figure out it's not going to work. The inner join at the tail end of the chain has basically converted both the joins to inner joins.
select ...
from
A a left outer join
B b on b.id = a.id inner join
C c on c.id2 = b.id2;
The problem seems simple yet it doesn't work right. Essentially after you ponder for a while you discover that you need to control the join order and do the inner join first. So the three queries below are equivalent ways to accomplish that. The first one is probably the one you're more familiar with:
select ...
from
A a left outer join
(select * from B b inner join C c on c.id2 = b.id2) bc
on bc.id = a.id
select ...
from
A a left outer join
B b inner join
C c on c.id2 = b.id2
on b.id = a.id
select ...
from
B b inner join
C c on c.id2 = b.id2 right outer join -- now they can be done in order
A a on a.id = b.id
You query is a little more complicated but ultimately the same issues came into play which is where the odd stuff came from. SQL has evolved and you have to remember that platforms didn't always have the fancy things like derived tables, scalar subqueries, CTEs so sometimes people had to write things this way. And then there were graphical query builders with a lot of limitations in older versions of tools like Crystal Report that didn't allow for complex join conditions...

Adding more condition while joining or in where which is better?

SELECT C.*
FROM Content C
INNER JOIN ContentPack CP ON C.ContentPackId = CP.ContentPackId
AND CP.DomainId = #DomainId
...and:
SELECT C.*
FROM Content C
INNER JOIN ContentPack CP ON C.ContentPackId = CP.ContentPackId
WHERE CP.DomainId = #DomainId
Is there any performance difference between this 2 queries?
Because both queries use an INNER JOIN, there is no difference -- they're equivalent.
That wouldn't be the case if dealing with an OUTER JOIN -- criteria in the ON clause is applied before the join; criteria in the WHERE is applied after the join.
But your query would likely run better as:
SELECT c.*
FROM CONTENT c
WHERE EXISTS (SELECT NULL
FROM CONTENTPACK cp
WHERE cp.contentpackid = c.contentpackid
AND cp.domainid = #DomainId)
Using a JOIN risks duplicates if there's more than one CONTENTPACK record related to a CONTENT record. And it's pointless to JOIN if your query is not using columns from the table being JOINed to... JOINs are not always the fastest way.
There's no performance difference but I would prefer the inner join because I think it makes very clear what is it that you are trying to join on both tables.

What's the difference between just using multiple froms and joins?

Say I have this query:
SELECT bugs.id, bug_color.name FROM bugs, bug_color
WHERE bugs.id = 1 AND bugs.id = bug_color.id
Why would I use a join? And what would it look like?
Joins are synticatic sugar, easier to read.
Your query would look like this with a join:
SELECT bugs.id, bug_color.name
FROM bugs
INNER JOIN bug_color ON bugs.id = bug_color.id
WHERE bugs.id = 1
With more then two tables, joins help make a query more readable, by keeping conditions related to a table in one place.
The join keyword is the new way of joining tables.
When I learned SQL it did not yet exist, so joining was done the way that you show in your question.
Nowadays we have things like joins and aliases to make the queries more readable:
select
b.id, c.name
from
bugs as b
inner join
bug_color as c on c.id = b.id
where
b.id = 1
Also there are other variations of joins, as left outer join, right outer join and full join, that is harder to accomplish with the old syntax.
Join syntax allows for outer joins, so you can go:
SELECT bugs.id, bug_color.name
FROM bugs, bug_color
LEFT OUTER JOIN bug_color ON bugs.id = bug_color.id
WHERE bugs.id = 1