Relational Division and SQL: 1 Example Relations and Queries
Relational Division and SQL: 1 Example Relations and Queries
Robert Soulé
Required Course
Databases
Programming Languages
2. Find all students who can graduate (i.e., who have taken all required
courses).
1
the SQL keyword DISTINCT. In terms of relational algebra, we use a selection
(σ), to filter rows with the appropriate predicate, and a projection (π) to
get the desired columns.
SELECT DISTINCT Student
FROM Taken
WHERE Course = ’Databases’
or Course = ’Programming Languages’;
Informally, we might read this query as “give me the set of students who
have taken a course that appears in the set of required courses”, or “the set
of students whose courses contain at least one course that is required.”
3. Find all students and the required courses that they have not taken
2
All Students First, we create a set of all student that have taken courses.
We can express this positively using a selection and projection:
CREATE TEMP TABLE AllStudent as
SELECT Student
FROM Taken ;
AllStudent Student
Robert
Susie
Julie
Emilie
All Students and Required Classes Next, we will create a set of stu-
dents and the courses they need to graduate. We can express this as a
Cartesian product, creating the pairs of the form (student,course):
CREATE TABLE StudentsAndRequired AS
SELECT DISTINCT AllStudent.student, Required.course
FROM AllStudent, Required ;
All Students and Required Classes Not Taken This is where our
query starts to get tricky. We want to find the subset of the relation we just
produced that includes the students and the required courses that they have
not taken. We are doing this as a first step towards finding the students who
cannot graduate.
The intuition is that we want to find all (student,course) pairs that are
in the relation StudentsAndRequired, but not in the relation Taken. This
should give us the set of students who cannot graduate, with the courses
that they still need to take:
3
CREATE TEMP TABLE StudentsAndRequiredNotTaken AS
SELECT * FROM StudentsAndRequired
WHERE NOT EXISTS (SELECT *
FROM Taken
WHERE StudentsAndRequired.student = Taken.student AND StudentsAndRequired.Course = Taken.Course);
Students Who Can Not Graduate From the previous relation, we can
apply a projection to get the set of students who cannot graduate.
CREATE TEMP TABLE CannotGraduate AS
SELECT Student FROM StudentsAndRequiredNotTaken;
CannotGraduate Student
Susie
Julie
Emilie
Emilie
Students Who Can Graduate This is the second tricky part of our
query. We find the subset of students who can graduate by looking at the
students in AllStudents who are not in the set of CannotGraduate. Put
another way, the set of all students except the students who cannot graduate:
CREATE TEMP TABLE CanGraduate AS
SELECT * FROM AllStudents
WHERE NOT EXISTS (SELECT *
FROM CannotGraduate
WHERE CannotGraduate.Student = AllStudents.Student);
CanGraduate Student
Robert
Robert
4
Re-write As a Single Query We can re-write the above set of queries
into a single query that does not use the temporary tables:
SELECT DISTINCT x.Student
FROM taken AS x
WHERE NOT EXISTS (
SELECT *
FROM required AS y
WHERE NOT EXISTS (
SELECT *
FROM taken AS z
WHERE (z.Student=x.Student)
AND (z.Course=y.Course)));
Re-write Using Except (or Minus) We can re-write the above to use
EXCEPT instead of NOT EXISTS:
SELECT Student FROM Taken
EXCEPT
SELECT Student FROM (
SELECT Student,Course
FROM (select Student FROM Taken), Required
EXCEPT
SELECT Student,Course FROM Taken);