Académique Documents
Professionnel Documents
Culture Documents
uke 10
INF212 - Vren 2002
a
SELECT class, country
FROM Classes
WHERE numGuns >= 10;
b
SELECT name AS shipName
FROM Ships
WHERE launched < '1918' ;
c
SELECT ship, battle
FROM Outcomes
WHERE result = 'sunk' ;
d
SELECT ship
FROM Ships
WHERE name = class;
e
SELECT name
FROM Ships
WHERE name LIKE 'R%';
f
We presume that there are no consecutive spaces in the names, and we ignore
the possibility of ships mentioned in Outcomes, but not present in the Ships
relation. This is because this task would not be doable with the limited set
of SQL that is taught in this chapter.
SELECT name
FROM Ships
WHERE name LIKE '% % %';
6.2.3
a
SELECT S.name
FROM Ships AS S, Classes as C
WHERE S.class = C.class AND
C.displacement > 35000;
b
SELECT S.name, C.displacement, C.numGuns
FROM Outcomes AS O, Classes AS C, Ships AS S
WHERE O.battle = 'Guadalcanal' AND
C.class = S.class AND
O.ship = S.name;
c
( SELECT name AS ship FROM Ships )
UNION
( SELECT ship FROM Outcomes );
If we assume that each and every class is named so after the rst ship in that
class, we have that Classes implicitly names ships.
d
( SELECT country FROM Classes WHERE type = 'bb' )
INTERSECT
( SELECT country FROM Classes WHERE type = 'bc' );
or equivalently
SELECT C1.country
FROM Classes AS C1, Classes as C2
WHERE C1.type = 'bb' AND
C2.type = 'bc' AND
C1.country = C2.country ;
e
SELECT O1.ship
FROM Outcomes AS O1, Outcomes AS O2, Battles AS B1, Battles AS B2
WHERE O1.ship = O2.ship AND
O1. result = 'damaged' AND
B1.name = O1.battle AND
B2.name = O2.battle AND
B1.date < B2.date ;
f
SELECT B1.battle AS battle
FROM Classes AS C1, Classes AS C2, Classes AS C3
Ships AS S1, Ships AS S2, Ships AS S3,
Outcomes AS O1, Outcomes AS O2, Outcomes AS O3
WHERE C1.country = C2.country AND
C2.country = C3.country AND
C1.class = S1.class AND
C2.class = S2.class AND
C3.class = S3.class AND
S1.name = O1.ship AND
S2.name = O2.ship AND
S3.name = O3.ship AND
O1.battle = O2.battle AND
O2.battle = O3.battle AND
O1.ship <> O2.ship AND
O2.ship <> O3.ship AND
O1.ship <> O3.ship ;
This is not an easy query to read, but if we look ahead and use more advanced
SQL, it becomes much simpler
SELECT battle
FROM Outcomes, Ships, Classes
WHERE ship=name AND
Ship.class = Class.class
GROUP BY battle, country
HAVING count(*) >= 3;
or, even prettier ;-)
SELECT battle
FROM ( ( Ships NATURAL JOIN Classes ) JOIN Outcomes ON ship=name )
GROUP BY battle, country
HAVING count(*) >= 3;
Note that we need to group by both battle and country, because we want
to consider three ships from each and every country within each and every
battle.
6.2.4
The relational-agebra query
SELECT L
FROM R1, R2, ... , Rn
WHERE C;
6.3.2
a
SELECT country
FROM Classes
WHERE numGuns >= ALL ( SELECT numGuns FROM Classes) ;
SELECT country
FROM Classes
WHERE NOT numGuns < ANY ( SELECT numGuns FROM Classes) ;
SELECT country
FROM Classes as C1
WHERE NOT EXISTS( SELECT *
FROM Classes AS C2
WHERE C1.numGuns < C2.numGuns ) ;
SELECT country
FROM Classes
WHERE numGuns IN ( SELECT MAX(numGuns)
FROM Classes ) ;
b
SELECT class
FROM Ships
WHERE name IN ( SELECT ship
FROM Outcomes
WHERE result = 'sunk' );
SELECT class
FROM Ships
5
c
SELECT name
FROM Ships
WHERE class IN ( SELECT class
FROM Classes
WHERE bore = 16 );
SELECT S.name
FROM Ships AS S
WHERE EXISTS ( SELECT *
FROM Classes as C
WHERE C.class = S.class AND
C.bore = 16 ) ;
And resultvise same, but simpler
SELECT name
FROM ( Classes NATURAL JOIN Ships )
WHERE bore = 16 ;
d
SELECT battle
FROM Outcomes
WHERE ship IN ( SELECT name
FROM Ships
WHERE class = 'Kongo' ) ;
SELECT O.battle
6
FROM Outcomes as O
WHERE EXISTS ( SELECT *
FROM Ships AS S
WHERE S.class = 'Kongo' AND
S.name = O.ship );
e
SELECT S.name
FROM ( Ships NATURAL JOIN Classes ) AS S
WHERE numGuns >= ALL ( SELECT numGuns
FROM Classes AS C
WHERE C.bore = S.bore );
SELECT S.name
FROM Ships AS S
WHERE EXISTS ( SELECT *
FROM Classes AS C
WHERE C.class = S.class AND
NOT C.numGuns < ANY ( SELECT C1.numGuns
FROM Classes AS C1
WHERE C1.bore = C.bore ) );
6.3.9
If we assume that there might be ships who's class isn't mentioned in the
Classes relation, we have
SELECT *
FROM Ships NATURAL LEFT OUTER JOIN Classes ;
If assume all ship's classes are in Classes, we get
SELECT *
FROM Ships s, Classes c
WHERE s.class = c.class ;
or
SELECT *
FROM Ships NATURAL JOIN Classes ;
6.3.10
If we allow name to be a NULL value, which isn't very reasonable, but
possible. Thus we get:
a
SELECT COUNT(*) AS numOfBattleshipClasses
FROM Classes
WHERE type = 'bb';
b
SELECT AVG(numGuns) AS meanNumGuns
FROM Classes
WHERE type = 'bb' ;
c
For this to be dierent from the previous, we must weigth a class by the
number of ships. We leave out classes without ships.
SELECT AVG(numGuns)
FROM Classes c, Ships s
WHERE c.class = s.class AND
c.type = 'bb' ;
d
SELECT class, MIN(launched)
FROM Ships
GROUP BY class;
e
SELECT class, COUNT(ship) AS shipCount
FROM ( Ships LEFT OUTER JOIN Outcomes ON name = ship )
WHERE result = 'sunk'
GROUP BY class;
f
Almost same as previous, but only allow classes with 3 or more ships, but
note how this is done. We rst get all classes that have more than three
ships, by the class IN statement that appears in the WHERE, then we
lter on those that actually sunk. This kind of subselect is necessary because
the ltering on number of ships in a class only can appear in the HAVING
clause.
g
SELECT country, AVG((bore*bore*bore)/2) AS meanShellWeight
FROM ( Ships INNER NATURAL JOIN Classes )
GROUP BY country;
10