SQL: Display Full Name + Filter By Subject
-
22-06-2021 - |
質問
Here are the following records inside my tables:
EnrollStudents
EnrollID StudentID SubjID
1 1 1
2 1 2
3 1 3
4 2 1
5 3 2
Students
StudentID UserID YearID FirstName LastName
1 1 1 John Doe
2 3 1 Peter Pan
3 7 1 Isaac Newton
Subjects
SubjID SubjCode YearID
1 English 1
2 Math 1
3 Science 1
and the output should be...
StudentID FullName
2 Peter Pan
3 Isaac Newton
I was able to come up with the following SQL statement (thanks to Ic.)
SELECT s.StudentID, s.FirstName + ' ' s.LastName AS FullName
FROM Students AS s
LEFT OUTER JOIN EnrollStudents AS es ON s.StudentID = es.StudentID
GROUP BY s.StudentID, s.FirstName, s.LastName
HAVING COUNT(DISTINCT(es.SubjID)) < (SELECT COUNT(*) FROM Subjects)
Is there a way that I can filter the query by subject? Let's say I select English, only Isaac Newton can enroll the subject.
解決
You can use a simpler query to find students not enrolled in a subject, e.g.:
select StudentID,
FirstName + ' ' + LastName as FullName
from Students
where StudentID not in (
select es.StudentID
from EnrollStudents es
inner join Subjects s on es.SubjID = s.SubjID
where s.SubjCode = 'English'
)
You could also write it as a left join, like this:
select s.StudentID,
s.FirstName + ' ' + s.LastName as FullName
from Students s
left outer join (
select distinct es.StudentID
from EnrollStudents es
inner join Subjects s on es.SubjID = s.SubjID
where s.SubjCode = 'English'
) ss on s.StudentID = ss.StudentID
where ss.StudentID is null
他のヒント
I think your query is needlessly complicated. You don't need a left outer join, for instance. Also, you can dispense with the subquery in the having clause:
SELECT s.StudentID, s.FirstName + ' ' s.LastName AS FullName
FROM Students AS s JOIN
EnrollStudents AS es
ON s.StudentID = es.StudentID
GROUP BY s.StudentID, s.FirstName, s.LastName
HAVING COUNT(DISTINCT(es.SubjID)) < COUNT(es.SubjID)
To get only English:
SELECT s.StudentID, s.FirstName + ' ' s.LastName AS FullName
FROM EnrollStudents AS es join
Students AS s
ON s.StudentID = es.StudentID join
Subjects su
on es.subjid = su.subjid
where su.subjcode in ('English')
GROUP BY s.StudentID, s.FirstName, s.LastName
HAVING COUNT(DISTINCT(es.SubjID)) < COUNT(es.SubjID)
When limited to a single subject, I think the "having" clause is irrelevant. Can you describe what you want the query to do?
This worked for me in MySQL. Had to concatenate a different way, but works like a charm
SELECT Students.StudentID, CONCAT(Students.FirstName, ' ', Students.LastName) AS FullName
FROM Students, Enrollstudents, Subjects
WHERE Subjects.SubjID = 2 <--- HERE IS THE BIT YOU CHANGE TO FILTER
AND EnrollStudents.SubjID = Subjects.SubjID
AND Students.StudentID = Enrollstudents.StudentID
And with the concat method you were using:
SELECT Students.StudentID, Students.FirstName + ' ' Students.LastName AS FullName
FROM Students, Enrollstudents, Subjects
WHERE Subjects.SubjID = 2
AND EnrollStudents.SubjID = Subjects.SubjID
AND Students.StudentID = Enrollstudents.StudentID
Note: You can do anything with the WHERE clauses that you want. To get everyone that isn't enrolled in a certain subject, you change the fourth line to:
AND EnrollStudents.SubjID <> Subjects.SubjID
or
AND NOT EnrollStudents.SubjID = Subjects.SubjID
(I think)