The
in-class exercise used the sailors/boats/reserves tables. I have
put DDL statements for these at ~cs186/fa03/sailors. If inclined,
you can load these into postgres and practice writing queries.
Just 'cd' to that directory, and run loadDB.sh.
Use the DDL to define
relations for Reserves and Sailors, defining keys/foreign keys, with a
constraint that age is between 16 and 110.
create table sailors (
sid int primary key,
sname varchar(38),
rating int,
age float check (age > 16 and age < 110)
);
create table boats (
bid int primary key,
bname varchar(25),
color varchar(21)
);
create table reserves (
sid int,
bid int,
day date,
foreign key (sid) references sailors (sid),
foreign key (bid) references boats (bid)
);
copy sailors from '/cygdrive/c/Eben/cs186/sailors/sailors_data' USING
DELIMITERS '|';
copy boats from '/cygdrive/c/Eben/cs186/sailors/boats_data' USING
DELIMITERS '|';
copy reserves from '/cygdrive/c/Eben/cs186/sailors/reserves_data' USING
DELIMITERS '|';
Find boat ids for boats which
have never been reserved
There are several ways to do
this. One is set difference, subtracting the set of all boats
from the set of boats that have been reserved:
(select bid from boats) except
(select bid from reserves);
Another way to do this is an outer join between boats and reservations,
finding boats with null reservations:
select b.bid from boats b left outer join reserves
on b.bid = reserves.bid
where sid is null;
Yet another was is to use a nested query:
select bid from boats where not exists
(select * from reserves where boats.bid = reserves.bid);
Note: if you want the list of bids to have no duplicates, you may need
to specify 'select DISTINCT'
Find sailor names sorted by
their earliest reservation date.
select sname from sailors natural join
reserves
group by sailors.sid, sname
order by min(day);
Change all sailors named “Bob”
to have the name “Robert”
update sailors set sname =
'Robert' where sname = 'Bob';
List each sailor’s name, along
with the number of reservations made by that sailor.
The following will give the count for
sailors who have made at least one reservation:
select sname, count(*)
from sailors, reserves
where sailors.sid = reserves.sid
group by sailors.sid, sname;
If you want the sailors who have made zero reservations, you should
union the above query with a query to get sailors with no reservations.