Reputation: 25
I have written a query which calculates student's GPAs from information across multiple tables:
SELECT Major DNO, DName Dept, FName, LName,
(SUM(g.gradepoint*c.Credits)/SUM(c.Credits)) GPA
FROM Student s, Enrolled_in e, Gradeconversion g, Course c, Department d
WHERE s.StuID=e.StuID and e.Grade=g.lettergrade and e.CID=c.CID and d.DNO=s.Major
GROUP BY e.StuID;
which produces this output:
+------+-----------------------+---------+----------+------------------+
| DNO | Dept | FName | LName | GPA |
+------+-----------------------+---------+----------+------------------+
| 600 | Computer Science | Linda | Smith | 3.3187500089407 |
| 600 | Computer Science | Tracy | Kim | 3.08235291873708 |
| 600 | Computer Science | Shiela | Jones | 3.05999999046326 |
| 600 | Computer Science | Dinesh | Kumar | 2.78947370930722 |
| 600 | Computer Science | Paul | Gompers | 2.89999998699535 |
| 600 | Computer Science | Andy | Schultz | 2.98823530533734 |
| 600 | Computer Science | Lisa | Apap | 3.32105263910796 |
| 600 | Computer Science | Jandy | Nelson | 3.2 |
| 600 | Computer Science | Eric | Tai | 3.01923077840071 |
| 600 | Computer Science | Derek | Lee | 3.61304346374843 |
| 600 | Computer Science | David | Adams | 3.3 |
| 600 | Computer Science | Steven | Davis | 3.18750002980232 |
| 600 | Computer Science | Charles | Norris | 3.57142857142857 |
| 600 | Computer Science | Susan | Lee | 3.5071428673608 |
| 600 | Computer Science | Mark | Schwartz | 2.9434782733088 |
| 600 | Computer Science | Bruce | Wilson | 3.05789474437111 |
| 600 | Computer Science | Michael | Leighton | 3.17058825492859 |
| 600 | Computer Science | Arthur | Pang | 2.89999998699535 |
| 520 | ECE | Ian | Thornton | 4 |
| 520 | ECE | George | Andreou | 2.94782609524934 |
| 540 | Chemical Engineering | Michael | Woods | 3.26666665960241 |
| 520 | ECE | David | Shieber | 3.375 |
| 540 | Chemical Engineering | Stacy | Prater | 3.06666667373092 |
| 520 | ECE | Mark | Goldman | 3.42307692307692 |
| 520 | ECE | Eric | Pang | 3.7562500089407 |
| 520 | ECE | Paul | Brody | 2.90526317295275 |
| 550 | Mathematical Sciences | Eric | Rugh | 3.82499998807907 |
| 100 | History | Jun | Han | 3.10500003099442 |
| 550 | Mathematical Sciences | Lisa | Cheng | 2.95384616118211 |
| 550 | Mathematical Sciences | Sarah | Smith | 3.09230767763578 |
| 550 | Mathematical Sciences | Eric | Brown | 2.98000001907349 |
| 550 | Mathematical Sciences | William | Simms | 3.8 |
| 50 | Cognitive Science | Eric | Epp | 3.11249998211861 |
| 50 | Cognitive Science | Sarah | Schmidt | 3.08125002682209 |
+------+-----------------------+---------+----------+------------------+
Now I need to find the tuples in this table which correspond to the students with the lowest GPA in each major My thought was to do something like this:
SELECT DNO, Dept, FName, LName, MIN(GPA) GPA FROM
(SELECT Major DNO, DName Dept, FName,
LName,(SUM(g.gradepoint*c.Credits)/SUM(c.Credits)) GPA
FROM Student s, Enrolled_in e, Gradeconversion g, Course c, Department d
WHERE s.StuID=e.StuID and e.Grade=g.lettergrade and e.CID=c.CID and d.DNO=s.Major
GROUP BY e.StuID) p
GROUP BY Dept;
but that produces:
+------+-----------------------+---------+----------+------------------+
| DNO | Dept | FName | LName | GPA |
+------+-----------------------+---------+----------+------------------+
| 540 | Chemical Engineering | Michael | Woods | 3.06666667373092 |
| 50 | Cognitive Science | Eric | Epp | 3.08125002682209 |
| 600 | Computer Science | Linda | Smith | 2.78947370930722 |
| 520 | ECE | Ian | Thornton | 2.90526317295275 |
| 100 | History | Jun | Han | 3.10500003099442 |
| 550 | Mathematical Sciences | Eric | Rugh | 2.95384616118211 |
+------+-----------------------+---------+----------+------------------+
The minimum GPA in each department is found, but it is associated with whatever student fname and lname happened to be listed first in that department, and not the fname and lname that actually had the lowest GPA. I know that when you use GROUP BY, every attribute in the SELECT that isn't part of the aggregate function should appear in the GROUP BY. I'm just not sure how to proceed with this query to get the values I'm looking for. Any help would be greatly appreciated as I'm quite new at this!
Upvotes: 2
Views: 122
Reputation: 3280
You need yet another level of nesting and another JOIN
to accomplish that. Using a VIEW
would provide you with reusability and easy query building.
So as a first step, store your original query in a view like so:
CREATE VIEW GPAS AS
SELECT Major DNO, DName Dept, FName, LName,
(SUM(g.gradepoint*c.Credits)/SUM(c.Credits)) GPA
FROM
Student s, Enrolled_in e, Gradeconversion g, Course c, Department d
WHERE s.StuID=e.StuID and e.Grade=g.lettergrade
and e.CID=c.CID and d.DNO=s.Major
GROUP BY e.StuID;
Now, to reproduce the first result you mentioned, is as easy as doing
select * from gpas
Now to the point: Apparently, your second query would be rewritten as
SELECT DNO, Dept, FName, LName, MIN(GPA) GPA
FROM GPAS p ORDER BY Dept.
But it would still return the same results, right? To achieve what you want, do:
select * from gpas g
join (select dept,MIN(GPA) mingpa from gpas group by dept) mingpas mg
on (g.dept=mg.dept and g.GPA=mg.mingpa)
You can see how easier and more comperhensive this gets using views. But, should you decide not to use them, replace every FROM GPAS
in the above queries with
FROM (YourOriginalQuery) AS somealias
Upvotes: 2