How to join three tables in sql server - sql

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

Related

How to list all entries between many to many relationships and indicate when there is a match

I've created a database and I would like to be able to retrieve all entries from 2 tables that are in a many to many relationship and indicate when there is a match.
You can find exemple with some dummy data in the screenshot attached with the expected result.
I'm not able to see how can I list all operators and all standards on the same table independently. I've done some test with full outer join but the result is not satisfactory.
SELECT o.Nom,s.Nom_Standard
from Formation as f
full OUTER join Operateurs as o
on o.Id_Operateur = f.Fk_Operateur
full OUTER JOIN Standards as s
on s.Id_Standard = ps.Fk_Standard
Thanks in advance.
Use a cross join to get the operators and standards:
select o.Nom, s.Nom_Standard
from Operateurs o cross join
Standards s ;
If you want to bring in information from Formation, use a left join:
select o.Nom, s.Nom_Standard,
(case when f.IdOperateur is not null then 'Yes' else 'No' end) as is_done
from Operateurs o cross join
Standards s left join
Formation f
on o.Id_Operateur = f.Fk_Operateur
s.Id_Standard = f.Fk_Standard;
See my comment on your question, however there is a way of getting what you want:
SELECT o.Nom, s.Nom_Standard, (CASE WHEN ISNULL(f.Id_Formation) THEN 'No' ELSE 'Yes' END) AS done
FROM Operateurs o
INNER JOIN Standards s
LEFT OUTER JOIN Formation f ON f.Fk_Operateur=o.Id_Operateur AND f.Fk_Standard=s.Id_Standard
ORDER BY o.Id_Operateur
But this is not using the middle table as a standard many to many join table and so could cause future confusion.

Is it true that all joins following a left join in a SQL query must also be left joins? Why or why not?

I remember this rule of thumb from back in college that if you put a left join in a SQL query, then all subsequent joins in that query must also be left joins instead of inner joins, or else you'll get unexpected results. But I don't remember what those results are, so I'm wondering if maybe I'm misremembering something. Anyone able to back me up on this or refute it? Thanks! :)
For instance:
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id -- this inner join might be bad mojo
Not that they have to be. They should be (or perhaps a full join at the end). It is a safer way to write queries and express logic.
Your query is:
select *
from customer c left join
ledger l
on c.id = l.customerid inner join
order o
on l.orderid = o.id
The left join says "keep all customers, even if there is no matching record in ledger. The second says, "I have to have a matching ledger record". So, the inner join converts the first to an inner join.
Because you presumably want all customers, regardless of whether there is a match in the other two tables, you would use a left join:
select *
from customer c left join
ledger l
on c.id = l.customerid left join
order o
on l.orderid = o.id
You remember correctly some parts of it!
The thing is, when you chain join tables like this
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id
The JOIN is executed sequentialy, so when customer left join ledger happens, you are making sure all joined keys from customer return (because it's a left join! and you placed customers to the left).
Next,
The results of the former JOIN are joined with order (using inner join), forcing the "the first join keys" to match (1 to 1) with the keys from order so you will end up only with records that were matched in order table as well
Bad mojo? it really depends on what you are trying to accomplish.
If you want to guarantee all records from customers return, you should keep "left joining" to it.
You can, however, make this a little more intuitive to understand (not necessarily a better way of writing SQL!) by writing:
SELECT * FROM
(
(SELECT * from customer) c
LEFT JOIN
(SELECT * from ledger) l
ON
c.id= l.customerid
) c_and_l
INNER JOIN (OR PERHAPS LEFT JOIN)
(SELECT * FROM order) as o
ON c_and_l.orderid (better use c_and_l.id as you want to refer to customerid from customers table) = o.id
So now you understand that c_and_l is created first, and then joined to order (you can imagine it as 2 tables are joining again)

How can i apply left outer join conditions on four tables?

i was trying to apply joins on 4 tables. but i could not find proper result for that.
i have 4 tables like 1.students,2.college,3.locations,4.departments. so i have same column sid in all tables which can be used to join conditions.
i want all matched rows from four tables as mentioned columns in select statement below and unmatched rows in left table which is left outer join work.
i have tried this syntax.
select
students.sname,
college.cname,
locations.loc,
department.dept
from students, college, locaions, departments
where student.sid=college.sid(+)
and college.sid=locations.sid(+)
and locations.sid=department.sid(+);
is this right ?
This is an old-fashioned way of outer-joining in an Oracle database. For Oracle this statement is correct; in other DBMS it is invalid.
Anyway, nowadays (as of Oracle 9i; in other DBMS much longer) you should use standard SQL joins instead.
select
s.sname,
c.cname,
l.loc,
d.dept
from students s
left outer join college c on c.sid = s.sid
left outer join locations l on l.sid = c.sid
left outer join departments d on d.sid = l.sid;
Given what you've shown it would appear that what you really want is
select s.sname,
c.cname,
l.loc,
d.dept
from students s
LEFT OUTER JOIN college c
ON c.SID = s.SID
LEFT OUTER JOIN locations l
ON l.SID = s.SID
LEFT OUTER JOIN departments d
ON d.SID = s.SID
The issue in your original query is that because an OUTER JOIN is an optional join, you can end up with NULL values being returned in one of the join fields, which then prevents any of the downstream values being joined. I agree with #ThorstenKettner who observes in a comment that SID is apparently a "student ID", but it's not reasonable or appropriate to have a "student ID" field on tables named COLLEGE, LOCATIONS, or DEPARTMENTS. Perhaps you need to update your design to allow any number of students to be associated with one of these entities, perhaps using a "join" table.
Best of luck.

Outer Joining SQL Tables?

I have three table in the Database -
Activity table with activity_id, activity_type
Category table with category_id, category_name
Link table with mapping between activity_id and category_id
I need to write a select statement to get the following data:
activity_id, activity_type, Category_name.
The issue is some of the activity_id have no entry in the link table.
If I write:
select a.activity_id, a.activity_type, c.category_name
from activity a, category c, link l
where a.activity_id = l.activity_id and c.category_id = l.category_id
then I do not get the data for the activity_ids that are not present in the link table.
I need to get data for all the activities with empty or null value as category_name for those not having any linking for category_id.
Please help me with it.
PS. I am using MS SQL Server DB
I believe you're looking for a LEFT OUTER JOIN for your activity table to return all rows.
SELECT
a.activity_id, a.activity_type, c.category_name
FROM activity a
LEFT OUTER JOIN link l
ON a.activity_id = l.activity_id
LEFT OUTER JOIN category c
ON c.category_id = l.category_id;
You should use proper explicit joins:
select a.activity_id, a.activity_type, c.category_name
from activity a
LEFT JOIN link l
ON a.activity_id = l.activity_id
LEFT JOIN category c
ON l.category_id = c.category_id
If writing this type of logic will be part of your ongoing responsibilities, I would strongly suggest that you do some research on joins, including the interactions between joins and where clauses. Joins and where clauses combine to form the backbone of query writing, regardless of the technology used to retrieve the data.
Most critical join information to understand:
Left Outer Join: retrieves all information from the 'left' table and any records that exist in the joined table
Inner Join: retrieves only records that exist in both tables
Where clauses: used to limit data, regardless of inner or outer join definitions.
In the example you posted, the where clause is limiting your overall data to rows that exist in all 3 tables. Replacing the where clause with appropriate join logic will do the trick:
select a.activity_id, a.activity_type, c.category_name
from activity a
left outer join link l --return all activity rows regardless of whether the link exists
on a.activity_id = l.activity_id
left outer join category c --return all activity rows regardless of whether the link exists
on c.category_id = l.category_id
Best of luck!
What about?
select a.activity_id, a.activity_type, c.category_name from category c
left join link l on c.category_id = l.category_id
left join activity a on l.activity_id = a.activity_id
Actually, the first join seems that it could be an inner join, because you didn't mention that there might be some missing elements there

Multiple join in mysql

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/