I have a table of students.
and a table of teachers.
SOME of the students (not all) will have a teacher assigned to them.
this is controlled in a 3rd table, matching those students with their teachers, via the studentID and teacherID
what i need the SQL to do, is to LEFT OUTER JOIN onto the 3rd table, which is then INNER JOINED onto the teacher's table (because not all students will appear in the 3rd table, but any teacher that appears in the 3rd table WILL appear in the teachers table).
i am looking to get a result of all student names, and teacher's name, where they are assigned (and null if not).
what i have so far looks like this, and it basically operates as a full INNER JOIN, and does not give me students who do not have teachers assigned:
SELECT firstname, teacherlastName
FROM tblstudents
left outer join [tblStudentRakazot]
ON tblstudents.studentid = [tblStudentRakazot].studentID
INNER JOIN tblteachers
ON [tblStudentRakazot].teacherid = tblteachers.teacherID
can someone pls give me a pointer here? i tried with placing brackets, but that didn't see, to help.
thanks!
You don't use an INNER JOIN but only another LEFT JOIN.
Think of tblStudents as your base. You want to get all of them, not filter anything out, and only attach optional info.
With the first left join, you attach a first info
Student -> TeacherAssignment
The TeacherAssignment can be null or not null.
Now you only attach another info - the teacher's full name pulled from tblTeachers.
Student -> TeacherAssignnent -> TeacherName
Do this with another LEFT JOIN. That attaches the info, where possible, i.e. where TeacherAssignment is not null.
This ignores rows where TeacherAssignment is null anyway.
SELECT firstname, teacherlastName
FROM tblstudents
left outer join
( select * from
[tblStudentRakazot] A INNER JOIN tblteachers B
ON A.teacherid = B.teacherID)AS C
ON tblstudents.studentid = C.studentID
You could move your INNER JOIN to a subquery
SELECT firstname, teacherlastName
FROM tblstudents
LEFT OUTER JOIN
( SELECT [tblStudentRakazot].studentID, tblTeachers.teacherlastName
FROM [tblStudentRakazot]
INNER JOIN tblteachers
ON [tblStudentRakazot].teacherid = tblteachers.teacherID
) teachers
ON tblstudents.studentid = teachers.studentID
Another option is to use a more complicated where clause.
SELECT firstname, teacherlastName
FROM tblstudents
LEFT JOIN [tblStudentRakazot]
ON tblstudents.studentid = [tblStudentRakazot].studentID
LEFT JOIN tblteachers
ON [tblStudentRakazot].teacherid = tblteachers.teacherID
WHERE [tblStudentRakazot] IS NULL
OR tblteachers.teacherID IS NOT NULL
However, SQL Server is pretty good at propogating predicates out of subqueries where it needs to, so I would favour the first approach for both readabilty and efficiency.
EDIT
I did not read the question properly, I thought you did not want records where the teacherID in tblStudentRakazot was NULL. If this is not an issue then you can simply use two LEFT JOINS, without the where clause as above:
SELECT firstname, teacherlastName
FROM tblstudents
LEFT JOIN [tblStudentRakazot]
ON tblstudents.studentid = [tblStudentRakazot].studentID
LEFT JOIN tblteachers
ON [tblStudentRakazot].teacherid = tblteachers.teacherID
SELECT b.student_firstname, teacherlastName
FROM thirdtable a
left join studenttbl b on a.studentid = b.studentid
left join teachertbl b on a.teacherid = b.teacherid
You can always use outer join if you are certain data in teacher table is unique. it will give same result as inner join.
You may not use a subquery as in #GarethD sample.
SELECT firstname, teacherlastName
FROM tblstudents
LEFT OUTER JOIN [tblStudentRakazot]
INNER JOIN tblteachers
ON [tblStudentRakazot].teacherid = tblteachers.teacherID
ON tblstudents.studentid = [tblStudentRakazot].studentID
But when looking more deeply execution plans of this query and query with subquery will likely be equivalent.
Related
Given this Diagram:
What is the right way to use join that will includes all necessary fields from different tables (person name, employee number, status of contracts, job name, department name, pcn/item name, country, and religion)? BUT I want also to include all persons that choose not to put either thier country or religion. I have this query:
SELECT persons.fullname, religions.religion_name, countries.country_name
FROM countries INNER JOIN (religions INNER JOIN (persons INNER JOIN
((jobs INNER JOIN (departments INNER JOIN pcns ON departments.ID = pcns.department_id) ON jobs.ID = pcns.job_id)
INNER JOIN (employees INNER JOIN contracts ON employees.ID = contracts.employee_id) ON pcns.ID = contracts.pcn_id)
ON persons.ID = employees.person_id) ON religions.ID = persons.religion) ON countries.ID = persons.country_id;
I used LEFT JOIN but I got an error. Right now, I only query all my tables except for countries and religions then I made a function that whenever a user clicks particular person this function will return its religion and/or country. I am just curious how to achieve it in a SELECT query.
How can we make multiple left and inner join in SQL Server
Following query not returning all Employees because of Inner join
SELECT * from Employee E
LEFT JOIN Participants P on E.EmpID=P.EmpID
INNER JOIN HRDetails H on D. DeptID=H.DeptID
Left JOIN SalaryDetails S on S.participantID=P.participantID
You have used an alias D. which does not refer to any table, this may cause error.
But to answer your question I think inner join would reduce the number of rows if not all DeptID matches between two tables.
I have 3 tables
STUDENTS
FEES_PAID
SUSPENDED
I want to get the details of the students who have paid the fees but not from SUSPENDED.
SELECT
ID
FROM
STUDENTS s
LEFT JOIN
SUSPENDED p ON s.ID = p.ID
INNER JOIN
FEES_PAID f ON f.ID = s.ID
WHERE
s.ID IS NULL
Unfortunately this does not work. Can any one suggest an efficient query?
Thanks in advance
You need to check if the second table is missing from the LEFT JOIN. So, you need to look at a column in that table. Change the WHERE to:
WHERE p.ID IS NULL
Alternatively, use NOT EXISTS:
SELECT s.ID
FROM STUDENTS s INNER JOIN
FEES_PAID f
ON f.ID = s.ID
WHERE NOT EXISTS (SELECT 1 FROM SUSPENDED p WHERE s.ID = p.ID);
Note that for both these queries, you will need to qualify the ID in the SELECT to specify the table where it comes from.
This should work:
SELECT
s.ID
FROM
STUDENTS s
LEFT JOIN
SUSPENDED p
ON s.ID=p.ID
INNER JOIN
FEES_PAID f
ON f.ID= s.ID
WHERE
p.ID IS NULL
I have got two queries:
select m.name, count(distinct a.kursnr)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on t.svnr = e.trainer
left outer join abhaltung a
on t.svnr = a.trainer
group by m.name, t.svnr;
select m.name, count(e.trainer)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on e.trainer = t.svnr
group by m.name, e.trainer;
The first one returns the correct number of courses (kursnr) and the second number the correct number of individual classes (einzeltraining) hold by a trainer. However, I cannot make one SQL statement which shows both values in one table. Any help would be appreciated. Thank you.
While there is likely a more efficient way to do this, I wanted to show you the easy way to combine any two queries that share a common field such as this:
select coalesce(q2.name, q1.name) As Name, q1.KursnrCount, q2.TrainerCount
from
( --original first query
select m.name, count(distinct a.kursnr) as KursnrCount
from trainer t
left outer join abhaltung a
on t.svnr = a.trainer
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e on svnr = e.trainer
group by m.name, t.svnr
) q1
full join
( --original second query
select count(e.trainer) as TrainerCount, m.name
from trainer t
left outer join einzeltraining e
on e.trainer = t.svnr
left outer join mitarbeiter m
on t.svnr = m.svnr
group by e.trainer, m.name
) q2 on q2.name = q1.name
You could also use an inner join or left join, instead of a full join, depending on how the name fields from those queries match up.
I need to go to two tables to get the appropriate info
exp_member_groups
-group_id
-group_title
exp_members
-member_id
-group_id
I have the appropriate member_id
So I need to check the members table, get the group_id, then go to the groups table and match up the group_id and get the group_title from that.
INNER JOIN:
SELECT exp_member_groups.group_title
FROM exp_members
INNER JOIN exp_member_groups ON exp_members.group_id = exp_member_groups.group_id
WHERE exp_members.member_id = #memberId
SELECT g.group_title
FROM exp_members m
JOIN exp_member_groups g ON m.group_id = g.group_id
WHERE m.member_id = #YourMemberId
If there is always a matching group, or you only want rows where it is, then it would be an INNER JOIN:
SELECT g.group_title
FROM exp_members m
INNER JOIN
exp_member_groups g
ON m.group_id = g.group_id
WHERE m.member_id = #member_id
If you want rows even where group_id doesn't match, then it is a LEFT JOIN - replace INNER JOIN with LEFT JOIN in the above.