term and then course name (both of which should also be ...cs348/w10/assignments/a1s… · 1. print...
TRANSCRIPT
1. Print a list of student numbers, student names, and final grades for each past class taught by Smith, ordered by
term and then course name (both of which should also be printed in the list).
select m.term, cname, s.snum, sname, grade
from student s, mark m, course c, class cl, professor p
where s.snum = m.snum
and m.cnum = cl.cnum and m.term = cl.term
and m.section = cl.section
and cl.cnum = c.cnum
and cl.pnum = p.pnum and pname= 'Smith'
order by m.term, cname
/* joining with the enrollment relation as well is useless, but OK (non-null foreign keys are already included in the
join conditions), but joining with the schedule relation might lose tuples */
or
with m(snum,cnum,term,section,grade,year,oterm) as
(select snum,cnum,term,section,grade, substr(term,2,2),
case when substr(term,1,1)='W' then 1
when substr(term,1,1)='S' then 2
else 3 end
from mark)
select m.term, cname, s.snum, sname, grade
from student s, m, course c, class cl, professor p
...
order by m.year, m.oterm, cname
2. How many students have received a mark in CS246?
select count (distinct snum)
from mark
where cnum = 'CS246'
/* it is unstated whether we want to include repetitions in the count */
3. Give the course data for a student transcript showing the course number, term, and grade (if completed) for
each course taken by the student whose number is 4321, ordered by term. Show the value -1 for courses in
progress.
select e.cnum, e.term, case when grade is null then -1 else grade end
from enrollment e left outer join mark m on (e.snum = m.snum
and e.cnum = m.cnum and e.term = m.term
and e.section = m.section)
where e.snum = 4321
order by e.term
4. List the course numbers for courses that were taught at some time but not taught in W07.
select cnum
from class
except
select cnum
from class
where term = 'W07'
/* alternatively, "taught at some time" implies presence in the enrollment relation (if assigned courses are not
necessarily "taught") -- in this case, use enrollment for both selects, rather than class */
5. Give a list of rooms that are used in W07 fewer than 3 times on Mondays or more than twice on Tuesdays.
select room
from schedule
where term = 'W07'
group by room, day
having (day = 'Monday' and count(*) < 3)
or (day = 'Tuesday' and count(*) > 2)
union
(select room
from schedule
where term = 'W07'
except
select room
from schedule
where term = 'W07'
group by room, day
having day = 'Monday')
/* the "except" part of union gives rooms not used at all on Mondays in W07, but it assumes that the query is
asking for rooms used at least once in W07; otherwise remove where clause from middle select statement; the
query could also be done by first forming a count for all rooms in W07: select room, day, count(*) as cnt
from schedule
where term = 'W07'
group by room, day
and then selecting from that based on the criteria */
6. What was the average grade in the section of any past course when someone named Lee was enrolled in that
section?
select m.cnum, m.term, m.section, avg(grade) as average
from mark m,
(select distinct cnum, term, section
from student s, mark m
where sname = 'Lee'
and s.snum = m.snum) lee
where m.cnum = lee.cnum and m.term = lee.term
and m.section = lee.section
group by m.cnum, m.term, m.section
/* distinct is not strictly needed in the nested select, since we're grouping on all three values and repeating all
entries an equal number of times does not change the average */
7. What are the names of professors who have taught the most number of distinct courses, and how many courses
did they teach?
with taught(pname,cnt) as
(select pname, count(*)
from (select distinct p.pnum, pname, cnum
from professor p, class c
where p.pnum = c.pnum) as pclass
group by pnum, pname)
select *
from taught
where cnt = (select max(cnt) from taught)
/* must include pnum when grouping, in case profs' names repeat */
8. Which third year students have taken all CO courses but have not enrolled in any CS classes?
select snum, sname
from student s
where snum not in
(select snum
from enrollment
where cnum like 'CS%')
and year = 3
and not exists
(select cnum
from course
where cnum like 'CO%'
except
select cnum
from enrollment
where enrollment.snum = s.snum)
/* the last part encodes relational divide */
9. Which courses have had more sections offered on Mondays and Wednesdays than on Tuesday and Thursdays?
select mw.cnum
from (select m.cnum, count(*) as cnt
from (select cnum, term, section
from schedule
where day = 'Monday') m,
(select cnum, term, section
from schedule
where day = 'Wednesday') w
where m.cnum = w.cnum and m.term = w.term
and m.section = w.section
group by m.cnum) as mw
left outer join
(select t.cnum, count(*) as cnt
from (select cnum, term, section
from schedule
where day = 'Tuesday') t,
(select cnum, term, section
from schedule
where day = 'Thursday') r
where t.cnum = r.cnum and t.term = r.term
and t.section = r.section
group by t.cnum) as tr
on mw.cnum = tr.cnum
where mw.cnt > tr.cnt or tr.cnt is null
/* left outer join and test for null catches courses not offered on T/Th */
10. Print a list of student numbers, student names, and cumulative average grades in decreasing order of average
grade for all students who have taken at least three courses and have a cumulative average over 85.
select s.snum, s.sname, avg(grade) as grd
from student s, mark m
where s.snum = m.snum
group by s.snum, s.sname
having count(*) >= 3 and avg(grade) > 85
order by grd desc
11. Print a list of student numbers, student names, and final grades for each past class taught by Smith.
12. Which students (snum, sname, and year) received a mark in CS246 and a mark in CS 240?
13. Assuming that the relation Minus1 has a single attribute named val and a single tuple with value -1, give the
course data for a student transcript showing the course number, term, and grade (if completed) of each course taken
by the student whose student number is 4321. Show the value -1 for courses in progress.
14. List the course numbers for courses that were taught at some time but not taught in W07.
15. Which third year students have taken all classes offered by Smith but have not enrolled in any classes offered
by Jones?
16. Translate the following E-R diagram into a relational schema that will not require the use of null values,
illustrated by a diagram in the style used for Parts 1 and 2.
Note that Owns.pname cannot be a foreign key, since Publisher.pname is not a primary key.
Illustrator, Manuscript, and Book must be separate relations from Work to avoid need for nulls.
cid title
Work
pages royalties
pname city
Publisher
cid
Contributor
name city
cid title
Manuscript
acqDate status
cid title
Book
pubDate price
pname cid title
Owns
cid title
Illustrator
illus_cid fee
17. List any constraints present in the E-R diagram that are not captured by the relational schema diagram.
Every work is owned by at most 2 publishers.
Every work is either a book or a manuscript, but not both.
Optional assumption: every publisher is in at least one city => need an additional constraint that every
publisher in Owns also appears in Publisher.
18. Give SQL DDL statements for creating each of the tables in your diagram. Be sure to include all the
constraints. (You’ll need to choose suitable domains for the attributes.)
create table publisher (
pname varchar(50) not null,
city varchar(20) not null,
primary key (pname,city) )
create table contributor (
cid int not null primary key,
name varchar(40),
city varchar(20) )
create table work (
cid int not null
references contributor,
title varchar(50) not null,
pages int,
royalties decimal(9,2),
primary key (cid,title) )
create table illustrator (
cid int not null,
title varchar(50) not null,
illus_cid int not null
references contributor(cid),
fee decimal(9,2),
primary key (cid,title),
foreign key (cid,title)
references work )
create table manuscript (
cid int not null,
title varchar(50) not null,
acqDate date,
status char(3),
primary key (cid,title),
foreign key (cid,title) references work )
create table book (
cid int not null,
title varchar(50) not null,
pubDate date,
price decimal(5,2),
primary key (cid,title),
foreign key (cid,title) references work )
create table owns (
pname varchar(50) not null,
cid int not null,
title varchar(50) not null,
primary key (pname,cid,title),
foreign key (cid,title)
references work,
constraint onlyTwo
check (2 >= (select count(pname)
from owns
where cid = n.cid
and title = n.title)) )
Since DB2 does not permit select in check constraints, could instead use a trigger to enforce it:
create trigger twoPublishers
no cascade before insert on owns
referencing new as n
for each row mode db2sql
when ( (select count(pname)
from owns
where cid = n.cid and title = n.title) = 2 )
signal sqlstate '34801'
('No more than two publishers can own a work')
In some SQL implementations, could use an assertion for the second constraint:
Create assertion coversWork
Check (not exists (
(select cid, title from work
except select cid, title from manuscript)
except select cid, title from book )
and not exists (
select cid, title from book
except select cid, title from manuscript )
and not exists (
select cid, title from manuscript
except select cid, title from book )
)
But again DB2 would have to rely on triggers (here, enforcing a certain workflow):
create trigger coversWork0
after insert on work
referencing new as n
for each row mode db2sql
insert into manuscript values
(n.cid,n.title,null,null)
create trigger coversWork1
after insert on book
referencing new as n
for each row mode db2sql
delete from manuscript
where cid=n.cid and title=n.title
create trigger coversWork2
after delete on book
referencing old as o
for each row mode db2sql
delete from work
where cid=o.cid and title=o.title