質問

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'
)

SQL Fiddle Example

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)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top