Abdul Rehman
Abdul Rehman

Reputation: 1794

Get min value based on foreign key

I am stuck on how to get a student's minimum score from marks table and student info from student table.

EDIT: sorry for not mentioning, but i need result for user 1, st1

student

id name
1  st1
2  st2

marks

student_id course_name marks
1          C++         55
1          OOP         65
1          AI          45  //need this lowest result for st1
2          C++         82
2          STATS       74
2          OS          20 // lowest marks are these for st2 or overall

Edit forgot to enter name st1:

Desired Output:

id name course_name MinMarks
1  st1  AI          45

I tried this query but it gives wrong course_name (C++) 1st row's course name

SELECT s.id, s.name, m.course_name, MIN(m.marks) FROM student s
JOIN marks m
ON s.id = m.student_id
Where s.id = 1

Output:

id name course_name MinMarks
1  st1  C++         45

Upvotes: 2

Views: 893

Answers (5)

Abdul Rehman
Abdul Rehman

Reputation: 1794

SELECT s.id, s.name, m.course_name, m.marks
FROM marks m
JOIN student s
ON m.student_id = s.id
WHERE m.student_id=1 AND m.marks = (SELECT MIN(marks) FROM marks WHERE student_id=1)

Upvotes: 0

Blake
Blake

Reputation: 151

try this:

Select s.id, s.name, m.course_name, m.marks From student s 
right join marks m 
on s.id = m.user_id where m.marks = MIN(m.marks);

Upvotes: 0

potashin
potashin

Reputation: 44581

You can use a subquery:

select *
from marks 
where marks = (select min(marks) from marks)

or left join:

select m.*
from marks m
left join (select min(marks) as marks from marks) m_min on m.marks = m_min.marks
where m_min.marks is not null

It guarantees you that if there is more then one student with the minimum mark it displays all of them.

left join can possibly improve performance, you can check your execution plan to be sure.

P.S.: If you also need to retrieve name from student table (is not stated in your desired output) you can do the join operation you did in your query:

using subquery:

select m.student_id
     , s.name
     , m.course_name
     , m.marks 
from student s
join marks m on s.id = m.student_id
where m.marks = (select min(marks) from marks)

using left join:

select m.student_id
     , s.name
     , m.course_name
     , m.marks 
from student s
join marks m on s.id = m.student_id
left join (select min(marks) as marks from marks) m_min on m.marks = m_min.marks
where m_min.marks is not null

Edit

As it turns out, OP needs a minimum marks per student's id (for the id = 1), so :

select m.student_id
     , s.name
     , m.course_name
     , m.marks 
from student s
join marks m on s.id = m.student_id
left join (select student_id, min(marks) as marks from marks group by student_id) p on s.id = p.student_id and p.marks = m.marks
where s.id = 1 and p.student_id is not null

Upvotes: 5

Gordon Linoff
Gordon Linoff

Reputation: 1269613

If you are looking for only one student with the minimum mark, I would suggest order by and limit:

SELECT s.id, s.name, m.course_name, m.marks
FROM student s JOIN
     marks m
     ON s.id = m.user_id
ORDER BY m.marks ASC
LIMIT 1;

This solution will not work if you are looking for all students that have the same minimum mark.

Upvotes: 0

Ryan-Neal Mes
Ryan-Neal Mes

Reputation: 6263

Try something like

select
  s.id,
  s.name,
  m.course_name,
  m.marks
from
  student s 

  inner join marks m on
    m.student_id = is.id

  inner join (
    select
      student_id,
      min(marks) min_mark
    from
      marks m
    group by
      student_id
  ) min_marks on
    min_marks.student_id = s.id and
    min_marks.student_id = m.student_id and
    min_marks.min_mark = m.marks

Upvotes: 0

Related Questions