Home > Back-end >  How to select values from table based on field with the same id?
How to select values from table based on field with the same id?

Time:01-31

Let's say I have following sql tables:

Table "student"

id first_name last_name
1 Lillian Nees
2 William Lorenz
3 Mary Moore
4 Giselle Collins
5 James Moultrie
6 John Rodriguez

Table "exam_result":

exam_result_id subject_id student_id mark
1 2 1 49
2 2 2 21
3 1 3 81
4 4 1 33
5 4 2 19
6 3 2 46
7 1 5 55
8 3 5 75
9 2 5 60
11 1 6 86
12 2 6 92
13 3 6 48
14 4 6 78

I need to select all students, who have all their exam marks <50 or haven't taken any exam at all.

So, in this case I need students with id 1, 2 and 4.

Closest thing I came up with is the following query, but it gives students with id 1, 2, 4 and 6. I don't need a student with id 6, since he has only 1 failed exam, not all of them.

SELECT DISTINCT s.id, s.first_name, s.last_name
FROM university.student s
LEFT JOIN
    university.exam_result er ON
        s.id = er.student_id
WHERE er.mark < 50 OR er.mark IS NULL;

I need it to work in both PostgreSQL and MariaDB, so I don't want anything specific to them.

CodePudding user response:

The query that works is:

SELECT DISTINCT s.id, s.first_name, s.last_name
FROM university.student s
WHERE NOT EXISTS(SELECT 1 FROM university.exam_result er WHERE s.id = er.student_id AND er.mark > 49);

Thanks, @jarlh for your comment.

CodePudding user response:

I would use a NOT EXISTS condition combined with a check for the marks

select s.*
from student s
where not exists (select * 
                  from exam_result er
                  where er.student_id = s.id)
   or 50 >= all (select er.mark
                 from exam_result er
                 where er.student_id = s.id)

CodePudding user response:

One option is doing this with aggregation, by ensuring the count of marks less than 50 is equal to all the count of their marks. When the student has 0 marks, the condition will still be satisfied.

SELECT s.id, s.first_name, s.last_name
FROM      student s
LEFT JOIN exam_result er ON s.id = er.student_id
GROUP BY s.id, s.first_name, s.last_name
HAVING COUNT(CASE WHEN er.mark < 50 THEN 1 END) = COUNT(er.mark)

Check the MariaDB demo and PostgreSQL demo.

  •  Tags:  
  • sql
  • Related