CountingAll

advertisement

Example: Counting All – a way to resolve universal quantification queries for many common cases.

Get names of guests who have reservations for all presidential suites (i.e. those that have two beds).

The idea is to count the number of presidential suites, and then count the number of different presidential suites for which a guest has a reservation. If the two are the same, the guest must have a reservation for all of them. (This assumes that what is identified as a presidential suite for which a guest has a reservation must be drawn from the list of all presidential suites. This is the case here and for many similar queries, but neither universal quantification queries nor relational division queries make this assumption.)

Even given this assumption, it is easy to do the counting wrong – e.g. count reservations rather than reservations for presidential suites, count reservations for presidential suites, but not different presidential suites. But with care, we can count properly.

Counting the number of presidential suites is easy. mysql> select count(*)

-> from Room

-> where NrBeds=2;

+----------+

| count(*) |

+----------+

| 3 |

+----------+

1 row in set (0.00 sec)

But if the table had allowed a room on more than one row, we would have had to be careful and use “count(distinct …).” mysql> select count(distinct RoomNr)

-> from Room

-> where NrBeds=2;

+-----------------------------+

| count(distinct RoomNr) |

+-----------------------------+

| 3 |

+-----------------------------+

1 row in set (0.00 sec)

We also have to be careful about counting the number of reservations for presidential suites. Don’t just count the number of reservations (of course). (104 also has 3 reservations)

mysql> select GuestNr, count(RoomNr)

-> from Reservation

-> group by GuestNr;

+----------+--------------------+

| GuestNr | count(RoomNr) |

+----------+--------------------+

| 101 | 3 |

| 102 | 1 |

| 103 | 1 |

| 104 | 3 |

| 105 | 1 |

| 106 | 1 |

+----------+--------------------+

6 rows in set (0.00 sec)

Don’t even just count the number of distinct reservations because a guest could have a reservation for three different rooms, some of which are not presidential suites. mysql> select GuestNr, count(distinct RoomNr)

-> from Reservation

-> group by GuestNr;

+----------+-----------------------------+

| GuestNr | count(distinct RoomNr) |

+----------+-----------------------------+

| 101 | 3 |

| 102 | 1 |

| 103 | 1 |

| 104 | 1 |

| 105 | 1 |

| 106 | 1 |

+----------+-----------------------------+

6 rows in set (0.00 sec)

But do count the number of distinct reservations for presidential suites. mysql> select GuestNr, count(distinct RoomNr)

-> from Reservation

-> where RoomNr<4

-> group by GuestNr;

+----------+-----------------------------+

| GuestNr | count(distinct RoomNr) |

+----------+-----------------------------+

| 101 | 3 |

| 102 | 1 |

| 103 | 1 |

| 105 | 1 |

| 106 | 1 |

+----------+-----------------------------+

5 rows in set (0.00 sec)

We can identify the presidential suites any way we wish, but perhaps we should identify them the same way for both the rooms and the reservations. mysql> select GuestNr, count(distinct RoomNr)

-> from Reservation

-> where RoomNr in (

-> select RoomNr

-> from Room

-> where NrBeds=2)

-> group by GuestNr;

+----------+-----------------------------+

| GuestNr | count(distinct RoomNr) |

+----------+-----------------------------+

| 101 | 3 |

| 102 | 1 |

| 103 | 1 |

| 105 | 1 |

| 106 | 1 |

+---------+-----------------------------+

5 rows in set (0.00 sec)

Now, we can use the having clause to see which counts (of the number of reservations for presidential suites and of the number of presidential suites) are the same. mysql> select GuestNr, count(distinct RoomNr)

-> from Reservation

-> where RoomNr in (

-> select RoomNr

-> from Room

-> where NrBeds=2)

-> group by GuestNr

-> having count(distinct RoomNr) = (

-> select count(distinct RoomNr)

-> from Room

-> where NrBeds=2);

+----------+-----------------------------+

| GuestNr | count(distinct RoomNr) |

+----------+-----------------------------+

| 101 | 3 |

+----------+-----------------------------+

1 row in set (0.00 sec)

To complete the query, we need the names of these guests. mysql> select Name

-> from Guest

-> where GuestNr in (

-> select GuestNr

-> from Reservation

-> where RoomNr in (

-> select RoomNr

-> from Room

-> where NrBeds=2)

-> group by GuestNr

-> having count(distinct RoomNr) = (

-> select count(distinct RoomNr)

-> from Room

-> where NrBeds=2));

+--------+

| Name |

+--------+

| Smith |

+--------+

1 row in set (0.00 sec)

Download