简体   繁体   中英

MySQL - Return rows only if all the values in WHERE clause are present

I have a database that stores exam records: tbl_exams stores the id and name of exams - there are only 9 exams and so only 9 records in this table as the exams are fixed and do not change. tbl_exam_details stores all the details for an exam entry, and includes the corresponding id from tbl_exams - there is a foreign key constraint for this. What I'm trying to do is create a query that returns rows only if all 9 exams have been taken by a certain student and the pass_or_fail field is '1' - I use tinyint(1) to store 1 which is pass, or 0 which is fail). This is essentially to check if all 9 exams have been passed.

This is what I have so far, however it is returning rows even when the student has only completed one or two exams:

SELECT tbl_exam_details.student_id, exam_name, exam_date, pass_or_fail FROM tbl_exam_details
INNER JOIN tbl_exams ON tbl_exams.exam_id = tbl_exam_details.exam_id
WHERE student_id = 1 AND pass_or_fail = 1
AND tbl_exam_details.exam_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
ORDER BY exam_details_id

What I need is for the query to only return rows once all 9 exams have been passed. So, if a student has passed 8 exams, the query should return 0 rows. If anyone could help me out it would be greatly appreciated.

SELECT ted.student_id, 
       exam_name, 
       exam_date, 
       pass_or_fail 
FROM tbl_exam_details ted
INNER JOIN tbl_exams 
   ON tbl_exams.exam_id = ted.exam_id
WHERE student_id = 1
  AND (SELECT COUNT(*)
       FROM tbl_exam_details ted2
       WHERE ted2.pass_or_fail = 1
         AND ted2.student_id = ted.student_id
      ) = 9  -- mean this student pass 9 exams
ORDER BY exam_details_id

Is this what you want?

SELECT ed.student_id
FROM tbl_exam_details ed
WHERE ed.student_id = 1 AND ed.pass_or_fail = 1 AND
      ed.exam_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
GROUP BY ed.student_id
HAVING COUNT(*) = 9;  -- or maybe COUNT(DISTINCT exam_id) = 9

This returns the student ids that have passed the 9 exams. It doesn't include any other information.

You can group_concat for a full list...

select x1.*
from 
(
select t1.*, group_concat(distinct exam_id order by exam_id separator '|') as x_list
from tbl_exam_details t1
where pass_or_fail = 1
group by student_id
) x1
where x_list = '1|2|3|4|5|6|7|8|9'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM