CS 4604 Homework #5 Solution Sketches
- pi_title (sigma_{director_name = "Steven Spielberg"} Movies)
- One solution is:
(SELECT title
FROM Movies
WHERE producing_studio = "Paramount"
AND format = "DVD")
INTERSECT
(SELECT title
FROM Movies
WHERE producing_studio = "Paramount"
AND format = "Video Cassette");
The following will not work:
SELECT title
FROM Movies
WHERE producing_studio = "Paramount"
AND format = "DVD"
AND format = "Video Cassette";
since there is no way a given tuple can satisfy both conditions in
the WHERE clause. The only way you can write this query with one
SQL block (SELECT/FROM/WHERE) is if you did a join of the Movies
relation with itself.
IsInDebtby(x,y) <- Customer(x,_,_,_,y), y<0.
// IsInDebtby contains customers and their negative balances.
// Everybody in this relation is in debt.
CannotbeMostNegative(x) <- IsInDebtby(x,y), IsInDebtby(z,m), x<>z, y > m.
// x cannot be the one in most debt because z has a balance (m) that is less
// than x's balance (which is y).
Answer(x) <- IsInDebtby(x,_), NOT CannotbeMostNegative(x).
(SELECT movieid
FROM Movies)
EXCEPT
(SELECT movieid
FROM Rented);
AllDVDMovies = pi_movieid (sigma_{format="DVD"} Movies);
//this contains all the DVD movies
AllCustomers = pi_customerid (Customers);
//this contains all the customers
Ideally = AllCustomers X AllDVDMovies;
// ideally, all customers have rented all DVD movies
Reality = Rented NaturalJoin AllDVDMovies;
// in reality, only those in the Rented relation actually happened;
// we join it with AllDVDMovies to make sure we only have DVD movies;
// just an extra precaution, really
// notice that Reality will have only two columns and the same schema as Ideally
BadCustomers = pi_customerid (Ideally - Reality);
// what is in Ideally but not in Reality, reflects customers
// and the movies they didn't see; these customers cannot be what we want
GoodCustomers = AllCustomers - BadCustomers;
// so everybody else must be it!
Answer = pi_name (GoodCustomers NaturalJoin Customers);
// we join GoodCustomers with Customers to get the names!
// since you know the story, the comments come before the commands now!
// first create a handy relation consisting of all the DVD movies
CREATE VIEW DVDMovies(movieid) AS
SELECT movieid
FROM Movies
WHERE format = "DVD";
// in the ideal case, every DVD movie has been seen by every customer
CREATE VIEW Ideally(movieid,customerid) AS
SELECT movieid, customerid
FROM DVDMovies, Customer;
// the reality is, of course, given by the actual rentals that have taken place
CREATE VIEW Reality(movieid,customerid) AS
SELECT movieid, customerid
FROM Rented, Movies
WHERE Rented.movieid = Movies.movieid
AND Movies.format = "DVD";
// the difference is clear
CREATE VIEW NotRentedby(movieid, customerid) AS
SELECT * FROM Ideally
EXCEPT
SELECT * FROM Reality;
// if some movie is not rented by somebody,
// then this movie cannot be in the answer!
CREATE VIEW BadDVDMovies(movieid) AS
SELECT movieid
FROM NotRentedby;
// so, the rest must be the answer!
CREATE VIEW Answer(movieid) AS
SELECT * FROM DVDMovies
EXCEPT
SELECT * FROM BadDVDMovies;
// hold on, the question wanted the titles!
CREATE VIEW WhatyouReallyWanted(title) AS
SELECT title
FROM Movies, Answer
WHERE Answer.movieid = Movies.movieid;
- This query is impossible unless we use recursion and/or perform computations
within Datalog queries.