COMS 4111, Spring 2013
HW2 Solutions
Q1. Graded by Abhas.
SELECT s.sid, s.sname, s.gpa
FROM student s
WHERE s.gpa > ALL (
SELECT s1.gpa
FROM student s1, major m
WHERE m.sid = s1.sid AND m.dname='Computer Sciences')
| SID |
SNAME |
GPA |
| 48 |
Natividad A. |
4 |
| 64 |
Fred Edwin B. |
4 |
| 67 |
Altenhaus Gloria |
4 |
| 73 |
Quarnty G. |
4 |
| 89 |
Longlastname A. |
4 |
| 90 |
Zappa F. |
4 |
Q2. Graded by Ningning.
The sid, name and gpa of Civil Engineering students enrolled in at least one course offered by Chemical Engineering:
SELECT s.sid, s.sname, s.gpa
FROM student s, enroll e, major m
WHERE s.sid = e.sid AND s.sid = m.sid AND
m.dname = 'Civil Engineering' AND
e.dname = 'Chemical Engineering'
Students enrolled in a course offered by a department other than Civil
Engineering and Chemical Engineering:
SELECT sid
FROM enroll
WHERE dname <> 'Civil Engineering' AND dname <> 'Chemical Engineering'
Students majoring in something other than Civil Engineering:
SELECT sid FROM major WHERE dname <> 'Civil Engineering'
The final query should include students returned by the first query above but not the second and third.
SELECT s.sid, s.sname, s.gpa
FROM student s, enroll e, major m
WHERE s.sid = e.sid AND s.sid = m.sid AND
m.dname = 'Civil Engineering' AND
e.dname = 'Chemical Engineering' AND
s.sid NOT IN (
SELECT sid
FROM enroll
WHERE dname <> 'Civil Engineering' AND dname <> 'Chemical Engineering') AND
s.sid NOT IN (SELECT sid FROM major WHERE dname <> 'Civil Engineering')
| SID |
SNAME |
GPA |
| 45 |
June Granson |
3.1 |
| 56 |
Starry J. |
3.3 |
Q3. Graded by Enrique.
SELECT d.dname, d.numphds, COUNT(p.pname) AS num_of_profs, d.numphds/count(p.pname) AS st_to_prof_ratio
FROM dept d, prof p
WHERE d.dname = p.dname
GROUP BY d.dname, d.numphds
HAVING COUNT(p.pname) >= 2
| DNAME |
NUMPHDS |
NUM_OF_PROFS |
ST_TO_PROF_RATIO |
| Industrial Engineering |
41 |
2 |
20.5 |
| Computer Sciences |
47 |
2 |
23.5 |
| Civil Engineering |
88 |
3 |
29.33333333333333333333333333333333333333 |
Note: We renamed the last two columns just for illustration purposes; we don't really care
if you did not rename the columns or, if you did, the names you used .
Q4. Graded by Abhas.
Let's attack the first part of the query: "For each department with at least 3
students
majoring in the department, print the department name, the total number
of students majoring in the department and the average age and average
GPA of all students majoring in this department". This information is in the major and student tables.
Subquery Q1 :
SELECT m.dname, COUNT(m.sid) AS cnt, AVG(s.age) AS avg_age, AVG(s.gpa) AS avg_gpa
FROM major m, student s
WHERE m.sid = s.sid
GROUP BY m.dname
HAVING COUNT(s.sid) >= 3
Now,
for the second part of the query: " ... followed by the same
information for the rising stars of this department (i.e., the number
of rising stars in the department as well as their average age and
average GPA)", we compute the stats as above but this time for the rsing stars only.
Subquery Q2:
SELECT m1.dname, COUNT(m1.sid) AS cnt, AVG(s1.age) as avg_age, AVG(s1.gpa) as avg_gpa
FROM major m1, student s1
WHERE s1.sid = m1.sid AND
s1.gpa >= 1.20*(
SELECT AVG(s2.gpa)
FROM student s2, major m2
WHERE s2.sid = m2.sid AND m2.dname = m1.dname) AND
s1.age < (
SELECT AVG(s2.age)
FROM student s2, major m2
WHERE s2.sid = m2.sid AND m2.dname = m1.dname)
GROUP BY m1.dname
Now
we need to combine these two subqueries into one so the results of both
are included in one table. For a better visualization, we keep the same
colors for the subqueries discussed above (Q1 in blue, Q2 in green); the new constructs that glue the two subqueries together are in red.
SELECT dept.dname, dept.cnt, dept.avg_age, dept.avg_gpa, rs.cnt AS rs_cnt, rs.avg_age AS rs_avg_age, rs.avg_gpa AS rs_avg_gpa
FROM (
SELECT m.dname, COUNT(m.sid) AS cnt, AVG(s.age) AS avg_age, AVG(s.gpa) AS avg_gpa
FROM major m, student s
WHERE m.sid = s.sid
GROUP BY m.dname
HAVING COUNT(s.sid) >= 3 ) dept, (
SELECT m1.dname, COUNT(m1.sid) AS cnt, AVG(s1.age) as avg_age, AVG(s1.gpa) as avg_gpa
FROM major m1, student s1
WHERE s1.sid = m1.sid AND
s1.gpa >= 1.20*(
SELECT AVG(s2.gpa)
FROM student s2, major m2
WHERE s2.sid = m2.sid AND m2.dname = m1.dname) AND
s1.age < (
SELECT AVG(s2.age)
FROM student s2, major m2
WHERE s2.sid = m2.sid AND m2.dname = m1.dname)
GROUP BY m1.dname ) rs
WHERE dept.dname = rs.dname
| DNAME |
CNT |
AVG_AGE |
AVG_GPA |
RS_CNT |
RS_AVG_AGE |
RS_AVG_GPA |
| Computer Sciences |
24 |
25.04166666666666666666666666666666666667 |
3.00416666666666666666666666666666666667 |
2 |
20.5 |
3.85 |
| Mathematics |
19 |
30.63157894736842105263157894736842105263 |
3.24210526315789473684210526315789473684 |
2 |
18.5 |
3.95 |
| Civil Engineering |
28 |
27.25 |
2.91428571428571428571428571428571428571 |
4 |
23.75 |
3.7 |
| Industrial Engineering |
20 |
27.7 |
2.77 |
5 |
21.6 |
3.84 |
Q5. Graded by Hahn.
To compute the enrollment of each course offered by each department,
including those
courses with zero enrollment, it is not sufficient to look at just the
enroll table - a course with zero enrololment will not appear in the
enroll table due to the key constraints. Information about courses,
regardless of enrollment, is available in the course table. So, we use
left outer join of the course and enroll tables to find the enrollment
of every course, including those with zero enrollment. (A simple join
between these two tables is not good because it will exclude courses
with zero enrollment since these courses do not appear in the
enroll table.)
The enrollment of each course (including those with zero
enrollment):
SELECT c1.dname, c1.cno, count(e1.sid)
FROM course c1 LEFT OUTER JOIN enroll e1 ON (e1.dname = c1.dname AND e1.cno = c1.cno)
GROUP BY c1.dname, c1.cno
The average enrollment of all courses (including those with zero
enrollment) offered by a specific department X:
SELECT count(e2.sid)/count(distinct c2.cno)
FROM course c2 LEFT OUTER JOIN enroll e2 ON (e2.dname = c2.dname AND e2.cno = c2.cno)
WHERE c2.dname = X
We are now ready to write our query by combining the above queries:
SELECT c1.dname, c1.cno, count(e1.sid)
FROM course c1 LEFT OUTER JOIN enroll e1 ON (e1.dname = c1.dname AND e1.cno = c1.cno)
GROUP BY c1.dname, c1.cno
HAVING COUNT(e1.sid) >= 1.2*(
SELECT count(e2.sid)/count(distinct c2.cno)
FROM course c2 LEFT OUTER JOIN enroll e2 ON (e2.dname = c2.dname AND e2.cno = c2.cno)
WHERE c2.dname = c1.dname)
| DNAME |
CNO |
COUNT(E.SID) |
| Computer Sciences |
302 |
18 |
| Civil Engineering |
561 |
12 |
| Sanitary Engineering |
561 |
1 |