------------------------------------------------------ -- COMP9311 24T1 Project 1 -- SQL and PL/pgSQL -- Template -- Name: Skye Tao -- zID: z5285195 ------------------------------------------------------ -- Q1: create or replace view Infoschool as select u.id from orgunits u join orgunit_types t on u.utype = t.id where u.longname like '%Information%' and t.name like '%School%'; create or replace view Q1(subject_code) as select s.code from subjects s, Infoschool i where s.offeredby = i.id and s.code like '____7%'; -- Q2: create or replace view COMP as select c.id from courses c join subjects s on s.id = c.subject where s.code like 'COMP%'; create or replace view Leclab as select c.id from courses c join classes cla on c.id = cla.course join class_types ctp on cla.ctype = ctp.id group by c.id having count(distinct cla.ctype) = 2 and bool_and(ctp.name in ('Lecture', 'Laboratory')); create or replace view Q2(course_id) as select c.id from courses c join COMP cp on c.id = cp.id join Leclab ll on c.id = ll.id; -- Q3: create or replace view Profs as select cs.course, count(*) as num_profs from course_staff cs join people p on cs.staff = p.id where p.title like 'Prof' group by cs.course having count(*) >= 2; create or replace view Enrolgret5 as select ce.student, count(*) as num_courses from course_enrolments ce join courses c on ce.course = c.id join semesters s on c.semester = s.id group by ce.student having count(*) >= 5 and min(s.year) >= 2008 and max(s.year) <= 2012; create or replace view Cpe as select er.student from Enrolgret5 er join course_enrolments ce on er.student = ce.student join Profs pro on ce.course = pro.course group by er.student having count(distinct case when pro.num_profs >= 2 then ce.course end) >= 5; create or replace view Q3(unsw_id) as select ple.unswid from people ple join Cpe cpe on ple.id = cpe.student where CAST(ple.unswid as text) like '320%'; -- Q4: create or replace view Avgmark as select c.id as course_id, o.id as faculty_id, s.id as semester_id, round(avg(ce.mark), 2) as average_mark from course_enrolments ce join courses c on ce.course = c.id join subjects sj on c.subject = sj.id join semesters s on c.semester = s.id join orgunits o on sj.offeredby = o.id join orgunit_types ot on o.utype = ot.id where ot.name like 'Faculty' and s.year = 2012 and ce.grade in ('HD', 'DN') group by c.id, o.id, s.id; create or replace view Maxavgmark as select faculty_id, semester_id, max(average_mark) as avg_mark from Avgmark group by faculty_id, semester_id; create or replace view Q4(course_id, avg_mark) as select ag.course_id, mag.avg_mark from Avgmark ag join Maxavgmark mag on ag.faculty_id = mag.faculty_id and ag.semester_id = mag.semester_id and ag.average_mark = mag.avg_mark; -- Q5: create or replace view Checker as select ce.course, count(*) as num_students from course_enrolments ce join courses c on ce.course = c.id join semesters s on c.semester = s.id group by ce.course having count(*) >= 500 and min(s.year) >= 2005 and max(s.year) <= 2015; create or replace view Staff_profs as select cs.course, count(*) as num_profs from course_staff cs join people p on cs.staff = p.id where p.title like 'Prof' group by cs.course having count(*) >= 2; create or replace view Q5(course_id, staff_name) as select cs.course, STRING_AGG(p.given, '; ' order by p.given) as staff_name from course_staff cs join people p on cs.staff = p.id join Checker ce on cs.course = ce.course join Staff_profs sp on cs.course = sp.course where p.title like 'Prof' group by cs.course order by staff_name; -- Q6: create or replace view Classes_usage as select r.id, count(distinct cla.id) as class_usage from rooms r join classes cla on r.id = cla.room join courses c on cla.course = c.id join semesters s on c.semester = s.id where s.year = 2012 group by r.id; create or replace view Max_room as select id from Classes_usage where class_usage = (select max(class_usage) from Classes_usage); create or replace view Room_subcode as select r.id, sj.code, count(distinct cla.id) as sub_usage from rooms r join classes cla on r.id = cla.room join courses c on cla.course = c.id join semesters s on c.semester = s.id join subjects sj on c.subject = sj.id where s.year = 2012 group by r.id, sj.code; create or replace view Max_sub_count as select id, max(sub_usage) as max_sub_usage from Room_subcode group by id; create or replace view Max_subcode as select rsc.id, rsc.code from Room_subcode rsc join Max_sub_count msc on rsc.id = msc.id and rsc.sub_usage = msc.max_sub_usage; create or replace view Q6(room_id, subject_code) as select mr.id, msc.code from Max_room mr join Max_subcode msc on mr.id = msc.id; -- Q7: create or replace view Copass as select ce.student, ce.course, c.semester, c.subject, ce.mark from courses c join course_enrolments ce on ce.course = c.id join subjects sj on sj.id = c.subject where ce.mark >= 50; create or replace view Proguoc as select co.student, pe.program, sum(sj.uoc) as count_uoc, min(s.starting) as prog_start, max(s.ending) as prog_end from program_enrolments pe join Copass co on co.student = pe.student and pe.semester = co.semester join subjects sj on co.subject = sj.id join semesters s on co.semester = s.id group by co.student, pe.program; create or replace view Checkprog as select pgc.student, pgc.program, pgc.prog_start, pgc.prog_end from Proguoc pgc join programs p on p.id = pgc.program where pgc.count_uoc >= p.uoc; create or replace view Progperiod as select cpg.student, o.id as orgid, count(distinct cpg.program) as finish_prog, min(cpg.prog_start) as startdate, max(cpg.prog_end) as enddate from Checkprog cpg join programs p on p.id = cpg.program join orgunits o on p.offeredby = o.id group by cpg.student, o.id having max(cpg.prog_end) - min(cpg.prog_start) <= 1000; create or replace view Q7(student_id, program_id) as select ppl.unswid, cpg.program from people ppl join Progperiod ppd on ppd.student = ppl.id join Checkprog cpg on cpg.student = ppd.student where ppd.finish_prog >= 2; -- Q8: create or replace view Convenor as select cst.staff, ce.course from course_staff cst join staff_roles sr on sr.id = cst.role join course_enrolments ce on ce.course = cst.course join courses c on ce.course = c.id join semesters s on s.id = c.semester where s.year = 2012 and sr.name like 'Course Convenor' group by cst.staff, ce.course; create or replace view Ehdn as select cov.staff, cov.course, count(*) filter (where ce.mark is not null) as total_stds, count(*) filter (where ce.mark >= 75) as distinct_stds from Convenor cov join course_enrolments ce on ce.course = cov.course group by cov.staff, cov.course; create or replace view Hdnr as select eh.staff, round(sum(eh.distinct_stds) * 1.0 / NULLIF(sum(eh.total_stds), 0), 2) as hdn_rate from Ehdn eh group by eh.staff; create or replace view sumroles as select a.staff, count(*) as sum_roles from affiliations a group by a.staff; create or replace view sameorg as select sr.staff, a.orgunit, count(*) as roles from sumroles sr join affiliations a on a.staff = sr.staff join orgunits o on o.id = a.orgunit group by sr.staff, a.orgunit having count(*) >= 3; create or replace view Q8 as with Rankhdn as ( select ppl.unswid as staff_id, sr.sum_roles, hd.hdn_rate, rank() over (order by hd.hdn_rate desc, sr.sum_roles desc) as rn from people ppl join Hdnr hd on hd.staff = ppl.id join sumroles sr on sr.staff = ppl.id join (select distinct staff from sameorg) as sg on sg.staff = ppl.id ) select staff_id, sum_roles, hdn_rate from Rankhdn where rn <= 20; -- Q9 create or replace view Sameprefix as select c.id as course_id, s.code as subject_code from courses c join subjects s on s.id = c.subject where s._prereq is not null and position(substr(s.code, 1, 4) in s._prereq) > 0; create or replace view Markvalid as select spf.course_id, spf.subject_code, ce.student, ce.mark from Sameprefix spf join course_enrolments ce on ce.course = spf.course_id where ce.mark is not null; create or replace view Rankcheck as select course_id, subject_code, student, mark, rank() over (PARTITION by course_id order by mark DESC) as rank from Markvalid mv; create or replace function Q9(unswid integer) returns setof text as $$ begin if not exists( select 1 from Rankcheck rc join people p on p.id = rc.student where p.unswid = Q9.unswid ) then return Next 'WARNING: Invalid Student Input [' || unswid || ']'; else return query SELECT rc.subject_code || ' ' || CAST(rc.rank AS TEXT) as result from Rankcheck rc join people p on rc.student = p.id where p.unswid = Q9.unswid; end if; end; $$ language plpgsql; -- Q10 create or replace function Q10(unswid integer) returns setof text as $$ --... SQL statements, possibly using other views/functions defined by you ... $$ language plpgsql;