Jason Chan wrote:

> I have a student Table and a SubjectGrade table
>
> Create Table Student(
> StudentID INT NOT NULL,
> StudentName VARCHAR(30)
> )
>
> Create Table SubjectGrade(
> StudentID INT NOT NULL,
> Subject VARCHAR(30) NOT NULL,
> Grade CHAR(1)
> )
>
> let's say have following record in SubjectGrade
>
> 1    Maths    A
> 1    Phys    B
> 1    Chem    A
> 2    Maths    A
> 2    Chem    A
> 3    Bio    C
> 3    Chem    A
>
> I want to find out students who have got A in both Maths and Chem
> How the SQL look like?

Philippe Poelvoorde wrote:

> Michael Stassen wrote:
Alternatively, use an IN list for the subject, then use a HAVING clause to limit the results to students with 2 matching rows, like this:

  SELECT StudentID, StudentName
  FROM Student s
  JOIN SubjectGrade sg ON s.StudentID = sg.StudentID
  WHERE sg.Subject IN ('Maths', 'Chem')
    AND sg.Grade = 'A';
  GROUP BY s.StudentID
  HAVING COUNT(*) = 2;

What if the student has 2 result in maths (or 2 in chemistry) ??? ;-)

Then the table has redundant rows!

But seriously, that's a different question -- one which would require more information to answer. In other words, based on the table description, I assume the combination of StudentID and Subject is unique in table SubjectGrade. While 'Maths', 'Phys', and 'Chem' sound categorical, I expect they were simplifications of actual course names, and the question amounts to finding students with 'A's in 2 specific courses. If the Subject is in fact categorical, so that a given student may have several grades (rows) for the same Subject, then I think we need more details. What, exactly, are thee requirements? Do we want students with at least one 'A' in each category? Students with all 'A's in each? Students with an 'A' average in each? Something else?

The advantage of the GROUP BY version of the query (if my assumptions are correct) is that it generalizes better than the self-join. For example, to find students with an 'A' in 'Bio', 'Maths', 'Phys', and 'Chem', you'd have to join the SubjectGrade table 2 more times in the self-join version, which gets unwieldy and inefficient. The GROUP BY version is easy to change, however:

  SELECT StudentID, StudentName
  FROM Student s
  JOIN SubjectGrade sg ON s.StudentID = sg.StudentID
  WHERE sg.Subject IN ('Maths', 'Chem', 'Bio', 'Phys')
    AND sg.Grade = 'A';
  GROUP BY s.StudentID
  HAVING COUNT(*) = 4;

You could also find students who have gotten 'A's in exactly 3, or at least 3, of those 4 subjects simply by modifying the HAVING clause to COUNT(*)=3, or COUNT(*)>=3, respectively.

On the other hand, to find a student with an 'A' in 'Chem' and a 'B' in 'Phys', for example, I think you'd probably use the self-join version, as you need to tie the grade to the subject (though you could tie them with CONCAT in the GROUP BY version, I suppose).

Michael




--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to