SQL: Chapter 6: Further Data Manipulation Techniques

SQL: Chapter 6: Further Data Manipulation Techniques


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:


col1    

300     



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:


aircra  

737     



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:


aircra  

ATP     
DC9     
737     



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:


aircra  

S60     
F24     



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:


name        address             

A Smithson  16 Bedford St       
C Evans     63 Kew Green        
T Pittman   The Little House    
K E         11 Rosedale Avenue  
Kendall                         



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:


name        address            

J Millar    Englewood Cliffs   
T Pittman   The Little House   



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:


name        address             

D Etheridge 4 Maylands Avenue    
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 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.


Return to Contents
Go on to Appendix A The Airline Database


Home Download Previous Next Email Top

© Copyright 1997 CHL. All rights reserved.