Reputation: 3
I have a database that has two tables. One holds the name of the classes a student can take (class_id, class_desc) and the other has the students information (id, fname, lname, class_id). I join the tables to get a roster of who is taking what class by joining on the class_id. How do I go about getting a roster of students that are taking class 'cl_2055' but not taking class 'cl_6910'?
Upvotes: 0
Views: 786
Reputation: 1271231
I like to use aggregation for this purpose
select si.fname, si.lname
from studentinformation si
where ci.classid in ('cl_2055', 'cl_6910')
group by si.fname, si.lname
having min(ci.classid) = 'cl_2055' and max(ci.classid) = 'cl_2055';
First, this assumes that the class identifiers are the ids and not the description (seems logical to me). If they are the descriptions, then you need to join in the class information.
How does this work? The where
clause filters down to students who might be in both classes. The group by
aggregates to a single row per student. And the having
keeps students who are only in "cl_055".
Upvotes: 1
Reputation: 1428
You really need to change your schema if you can. You should have three tables. Student, Class and StudentClass, (StudentClass contains a pointer to each of the other tables.
But if you insist on using the schema you have...
SELECT
*
FROM
students
WHERE
class_id = 'cl_2055'
AND id NOT IN (SELECT id FROM students where class_id = 'cl_6910')
This assumes the id is not unique, and you are using ID to represent students. If you are using ID to represent records, then you will need the second approach:
SELECT
*
FROM
students students_in_2055
WHERE
class_id = 'cl_2055'
AND NOT EXISTS (
SELECT 1
FROM students students_in_6910
WHERE students_in_6910.class_id = 'cl_6910'
AND students_in_2055.fname = students_in_6910.fname
AND students_in_2055.lname = students_in_6910.lname
)
Upvotes: 1