6. Introduction
This section returns to the SELECT statement and considers some
slightly more complex queries which demonstrate the flexibility
and strength of SQL as a data manipulation language.
6.1 Sub-Queries.
Example 6.1.1 - List the description of the aircraft with
the largest seating capacity.
This appears to be a very straight forward and simple query. But
it requires a query which will need to compare every aircraft
row with all other rows of the aircraft table to find the one
row for the aircraft with the largest seating capacity.
The SQL needed to find the largest seating capacity (the largest
value of NoSeats) is simply:
SELECT MAX(NoSeats)
FROM Aircraft;
Result:
But to which AircraftType does this seating capacity belong? We
need to list the AircraftType which corresponds to this value
of NoSeats, ie
SELECT AircraftType
FROM Aircraft
WHERE NoSeats = "largest seating capacity"
SQL allows us to specify a sub-query within the WHERE clause which
is executed before the main outer query to return one or
more rows which may then be compared with the rows returned by
the outer query. Hence putting the above queries together the
required SQL is as follows.
SELECT AircraftType
FROM Aircraft
WHERE NoSeats = ( SELECT MAX(NoSeats)
FROM Aircraft );
Result:
Note the sub-query appears is in brackets indicating that it will
return its result before the execution of the outer query.
This query could have been alternatively expressed as:
SELECT AircraftType
FROM Aircraft
WHERE NoSeats >= ALL ( SELECT NoSeats
FROM Aircraft );
Example 6.1.2 - List all aircraft which are not allocated
to any timetabled Flights
For this example we will consider the SQL components required
for each part of the query. Firstly we need to obtain a list of
aircraft types from the Flights tables; those aircraft which are
allocated to one or more timetabled flights, ie:
SELECT DISTINCT AircraftType
FROM Flights;
Result:
We require the AircraftTypes recorded in the Aircraft table which
do not appear in this list,ie:
(Craft table created earlier will be used for this example.)
SELECT AircraftType
FROM Craft
WHERE AircraftType NOT IN ("the list of allocated aircraft")
Putting these two queries together as before gives:
SELECT AircraftType
FROM Craft
WHERE AircraftType NOT IN
( SELECT DISTINCT AircraftType
FROM Flights );
Result:
Exercise 8.
1. By use of the IN operator and a sub-query list the names and
addresses of passengers with tickets for flight BD80.
2. List the names and addresses of passengers with Standby Single
(SBS) or Standard Return (SDR) tickets for flight BD54.
3. Provide an alternative to the SQL used in Example 6.1.2.
4. Find the AircraftType with the smallest seating capacity:
a) using an appropriate aggregate function;
b) without using an aggregate function.
6.2 Correlated Subqueries.
In the previous examples of subqueries each subquery was seen
to executed once; returning its result for use by the main (outer)
query.
In correlated sub-queries the sub-query executes once for each
row returned by the outer query.
Example 6.2.1 - List the names and addresses of passengers
with tickets made up of itineraries with only one flight.
SELECT Name, Address
FROM Passenger P
WHERE 1 = ( SELECT COUNT(*)
FROM Ticket T, Itinerary I
WHERE P.Pid = T.Pid AND
T.TicketNo = I.TicketNo );
Result:
For each row in the passenger table the value of Pid for that
row is passed into the subquery. The subquery executes once for
each value of Pid passed from the outer query and returns the
value of COUNT (the number of rows in the ticket-itinerary
join, ie flight legs, which satisfy the subquery WHERE condition,
ie flights for this Pid) to the WHERE clause in the outer
query. Where COUNT equals one for the current Pid its corresponding
row in the passenger table is listed in the result.
6.2.1 Testing for Existence.
The EXISTS operator enables us to test whether or not a subquery
has returned any rows.
EXISTS evaluates to true if one or more rows have been
selected and evaluates to false if zero rows have been selected.
NOT EXISTS evaluates to true if zero rows have been selected
and evaluates to false if one or more rows have been selected.
Example 6.2.2 - List the names and addresses of passengers
who purchased their Tickets on 01-AUG-92.
SELECT Name, Address
FROM Passenger P
WHERE EXISTS ( SELECT *
FROM Ticket T
WHERE P.Pid = T.Pid AND
T.TicketDate = '01/08/94 );
Result:
6.3 Set Operators.
We have seen how a query may be composed of subqueries whose results
are returned for evaluation within a WHERE clause.
We can also combine the results of pairs of queries and/or subqueries
by using the following Set Operators.
MINUS returns query difference; ie all rows in the result of the
first query which do not appear in the second query.
INTERSECTION returns common rows; ie only those rows which appear
in the results of both the first query and the second query.
UNION combines query results; ie returns the distinct rows
returned by either the first query or the second query.
It is important to note that queries to be operated on by these
operators must be union compatible, ie the SELECT clauses of both
queries must contain the same number and type of columns.
(Note MINUS and INTERSECTION are included here for completeness
they are NOT available in Ingres.)
6.3.1 Query Difference. (Minus not available in Ingres)
The MINUS operator takes as its operands, the results of two separate
queries and returns (as its result) the rows from the first query
which do not appear in the results of second query.
Example 6.3.1 - Find names of the airports from which direct
flights may be taken to all of the following destinations:
BELF (Belfast)
BIRM (Birmingham)
EDIN (Edinburgh)
EMID (East Midlands)
LBDR (Leeds/Bradford)
LVPL (Liverpool)
TEES (Teeside)
SELECT AName
FROM Airport A
WHERE NOT EXISTS
( ( SELECT DISTINCT F.ToAirport
FROM Flight F
WHERE F.ToAirport IN ('BELF','BIRM','EDIN',
'EMID','LBDR','LVPL','TEES') )
MINUS
( SELECT DISTINCT T.ToAirport
FROM Flight T
WHERE A.Airport = T.FromAirport ) );
This query would return Heathrow as the only airport.
The first subquery returns all flight destinations (airports)
which exist in the Flights table corresponding with the given
list.
The second subquery (correlated) takes each airport in turn from
the Airport table (outer query) as a departure point (FromAirport)
and generates a list of all possible direct destinations (ToAirport).
The MINUS operator compares the set of available destination airports
with the set of direct destinations possible from each departure
point (Airport). If there are no airports in the first query which
are not in the second, then we have found a departure point from
which we can reach all of the available destinations directly.
If there are zero rows returned, ie the list of available destinations
not reached is zero, then the NOT EXISTS evaluates to true and
the current ANAME from the Airport table is listed in the result.
6.3.2 Common Rows. (Intersection not available in Ingres)
The INTERSECT operator allows us to find the common rows from
the results of two separate queries (or subqueries). The following
example shows the intersection of two queries.
Example 6.3.2 - Find the Names and Addresses of passengers
flying from HROW (Heathrow) to BIRM (Birmingham) and from BIRM
to HROW. (Not necessarily on the same ticket.)
SELECT Name, Address
FROM Passenger P, Ticket T, Itinerary I, Flight F
WHERE P.Pid = T.Pid AND
T.TicketNo = I.TicketNo AND
I.FlightNo = F.FlightNo AND
F.FromAirport = 'HROW' AND
F.ToAirport = 'BIRM'
INTERSECT
SELECT Name, Address
FROM Passenger P, Ticket T, Itinerary I, Flight F
WHERE P.Pid = T.Pid AND
T.TicketNo = I.TicketNo AND
I.FlightNo = F.FlightNo AND
F.FromAirport = 'BIRM' AND
F.ToAirport = 'HROW' ;
Result would be:
NAME ADDRESS
----------- ---------------------------
G B Davis 25 Allenby Road
R H Miller 155 Kingston Road
The first query returns the names and addresses of passengers
flying from Heathrow to Birmingham.
The second query returns the names and addresses of passengers
flying from Birmingham to Heathrow.
The INTERSECT operator returns the rows from the first query which
also appear in the rows from the second query, ie those passengers
flying from Heathrow to Birmingham and from Birmingham to Heathrow.
6.3.3 Combining Results.
The UNION operator allows us to combine distinct rows from
the results of two separate queries (or subqueries) The following
example shows the union of two queries.
Example 6.3.3 - Find the Names and Addresses of passengers
flying from HROW (Heathrow) to BIRM (Birmingham) and from BIRM
to HROW or both.
SELECT Name, Address
FROM Passenger P, Ticket T, Itinerary I, Flight F
WHERE P.Pid = T.Pid AND
T.TicketNo = I.TicketNo AND
I.FlightNo = F.FlightNo AND
F.FromAirport = 'HROW' AND
F.ToAirport = 'BIRM'
UNION
SELECT Name, Address
FROM Passenger P, Ticket T, Itinerary I, Flight F
WHERE P.Pid = T.Pid AND
T.TicketNo = I.TicketNo AND
I.FlightNo = F.FlightNo AND
F.FromAirport = 'BIRM' AND
F.ToAirport = 'HROW' ;
Result:
The first query returns the names and addresses of passengers
flying from Heathrow to Birmingham.
The second query returns the names and addresses of passengers
flying from Birmingham to Heathrow.
The UNION operator returns the rows from the first query plus
the rows from the second query and removes any resulting duplicates.
Hence we see listed those passengers who are either flying from
Heathrow to Birmingham, or who are flying from Birmingham to Heathrow,
or both.
Exercise 9.
Give the SQL required to:
1. List the names and addresses of any passenger who on a single
ticket have more than 5 flights.
2. Find the names of those passengers who are taking all
of the flights which
J Millar is taking.
3. Rewrite the SQL statement given for Example 6.3.2 so that it
compares flights for the same ticket and hence find those passenger's
with return tickets HROW to BIRM and back. (Note. You will
need to use correlated sub-queries and an alternative query strategy
to find the intersection.)
4. Using correlated sub-queries find the Names of those passengers
with a ticket to fly from HROW (Heathrow) to PARI (Paris) without
a return flight to HROW; ie those passengers with non-return
tickets.
col1
300
aircra
737
aircra
ATP
DC9
737
aircra
S60
F24
name address
A Smithson 16 Bedford St
C Evans 63 Kew Green
T Pittman The Little House
K E 11 Rosedale Avenue
Kendall
name address
J Millar Englewood Cliffs
T Pittman The Little House
name address
D Etheridge 4 Maylands Avenue
G B Davis 25 Allenby Road
R H Miller 155 Kingston Road
Return to Contents
Go on to Appendix A The Airline Database
© Copyright 1997 CHL. All rights reserved.