Reputation: 5731
I have a university practical next week on databases. I need to create 15 queries around a scheme on a university, which looks as follows:
I have completed 14 of the queries but I am stuck on this one:
I have been reading up on not exists queries, but I just don't even know where to start! I created this piece of code:
select students.student_no, fname, lname, count(module_code)
from students left join take_exam using (student_no)
group by student_no
having count(module_code) < 19
order by lname;
This returns all students who DON'T take all 19 modules. However, I hate the code as it involves having < 19, which meant if the amount of modules ever changed later, this value would need changes which is inefficient.
Can anyone point me in the right direction and give me some guidance on using 'not exists' queries?
Thanks, Andrew
Upvotes: 1
Views: 1197
Reputation: 7986
Using not exists
:
select *
from Student s1
where not exists
(select 1
from Module
where Module_Code not in
(select Module_Code
from Take_Exam
where Student_No = s1.Student_No)
Explanation :
For each student s
in the table Student
, we'll add s
to the result, iff :
not exists any module in table Module
such that this module is not mapped to student s
in table Take_Exam
.
It's not intuitive, but it's exactly the same as : "all the students who take every module"
Upvotes: 1
Reputation: 34367
I think, you can get distinct count of modules from module table
and then use that in comparison e.g. below:
select students.student_no, fname, lname, count(t.module_code)
from module m, students join take_exam t using (student_no)
group by student_no
having count(t.module_code) = count(distinct(m.module_code))
order by lname;
Please note: I changed the condition to =
and join to inner join
as you wanted students taking all modules.
EDIT: Using notExit:
select students.student_no, fname, lname
from students
WHERE NOT EXISTS (select *
from module m, students join take_exam t using (student_no)
group by student_no
having count(t.module_code) < count(distinct(m.module_code))
group by student_no
)
order by lname;
Upvotes: 0
Reputation: 41418
Without completely answering your homework for you, here's a hint that might help:
Try looking at it from another angle. Students that answered all module question will not have any null fields with a left join to the module table, correct?
Also,you probably don't need a left outer join to the table_exam
... since you want only students having taken the exam.
Upvotes: 1