Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Queries

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 6

http://webpages.uncc.edu/xwu/5160/sailors.

txt

Q17) Compute increments for the ratings of persons who have sailed two different
boats on the same day.
SELECT S.sname, S.rating+1 AS rating
FROM Sailors S, Reserves R1, Reserves R2
WHERE S.sid = R1.sid AND S.sid = R2.sid
AND R1.day = R2.day AND R1.bid <> R2.bid

Q5) Find the names of sailors who have reserved a red or a green boat.
SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid
AND (B.color = red OR B.color = green)

6) Find the names of sailors who have reserved both a red and a green boat.
SELECT S.sname
FROM Sailors S, Reserves R1, Boats B1, Reserves R2, Boats B2
WHERE S.sid = R1.sid AND R1.bid = B1.bid
AND S.sid = R2.sid AND R2.bid = B2.bid
AND B1.color=red AND B2.color = green

The previous query is difficult to understand (and also quite inefficient to execute,
as it turns out). In particular, the similarity to the previous OR query (Query Q5) is
completely lost. A better solution for these two queries is to use UNION and INTERSECT.
The OR query (Query Q5) can be rewritten as follows:
SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = red
UNION
SELECT S2.sname
FROM Sailors S2, Boats B2, Reserves R2
WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color = green
This query says that we want the union of the set of sailors who have reserved red
boats and the set of sailors who have reserved green boats. In complete symmetry, the
AND query (Query Q6) can be rewritten as follows:
SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = red

INTERSECT
SELECT S2.sname
FROM Sailors S2, Boats B2, Reserves R2
WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color = green

Our next query illustrates the set-difference operation in SQL.


(Q19) Find the sids of all sailors who have reserved red boats but not green boats.
SELECT R.sid
FROM Boats B, Reserves R
WHERE R.bid = B.bid AND B.color = red
EXCEPT
SELECT R2.sid
FROM Boats B2, Reserves R2
WHERE R2.bid = B2.bid AND B2.color = green

In contrast to the default that


duplicates are not eliminated unless DISTINCT is specified in the basic query form, the
default for UNION queries is that duplicates are eliminated! To retain duplicates, UNION
ALL must be used;

Subqueries are usually fine unless they are dependent subqueries (also known
as correlated subqueries). If you are only using independent subqueries and they are using
appropriate indexes then they should run quickly. If you have a dependent subquery you
might run into performance problems because a dependent subquery typically needs to be
run once for each row in the outer query. So if your outer query has 1000 rows, the
subquery will be run 1000 times. On the other hand an independent subquery typically only
needs to be evaluated once.
If you're not sure what is meant by a subquery being dependent or independent here's a
rule of thumb - if you can take the subquery, remove it from its context, run it, and get a
result set then it's an independent subquery.
If you get a syntax error because it refers to some tables outside of the subquery then its
a dependent subquery.
The general rule of course has a few exceptions. For example:

Many optimizers can take a dependent subquery and find a way to run it efficiently
as a JOIN. For example an NOT EXISTS query might result in an ANTI JOIN query
plan, so it will not necessarily be any slower than writing the query with a JOIN.

MySQL has a bug where an independent subquery inside an IN expression is


incorrectly identified as a dependent subquery and so a suboptimal query plan is used.
This is apparently fixed in the very newest versions of MySQL.
If performance is an issue then measure your specific queries and see what works best for
you.

We have already seen the set-comparison operators EXISTS, IN, and UNIQUE, along
with their negated versions. SQL also supports op ANY and op ALL, where op is one of
the arithmetic comparison operators {<, <=, =, <>, >=, >}. (SOME is also available,
but it is just a synonym for ANY.)
(Q22) Find sailors whose rating is better than some sailor called Horatio.
SELECT S.sid
FROM Sailors S
WHERE S.rating > ANY ( SELECT S2.rating
FROM Sailors S2
WHERE S2.sname = Horatio )

To understand comparisons involving ANY, it is useful to


think of the comparison being carried out repeatedly. In the example above, S.rating
is successively compared with each rating value that is an answer to the nested query.
Intuitively, the subquery must return a row that makes the comparison true, in order
for S.rating > ANY . . . to return true.

This formulation of the query illustrates how queries involving


INTERSECT can be rewritten using IN, which is useful to know if your system does not
support INTERSECT. Queries using EXCEPT can be similarly rewritten by using NOT IN.

Our next example illustrates how the division operation in relational algebra can be
expressed in SQL.
(Q9) Find the names of sailors who have reserved all boats.
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS (( SELECT B.bidFROM Boats B )
EXCEPT
(SELECT R.bid
FROM Reserves R
WHERE R.sid = S.sid ))
Notice that this query is correlatedfor each sailor S, we check to see that the set of
boats reserved by S includes all boats. An alternative way to do this query without
using EXCEPT follows:
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS ( SELECT B.bid
FROM Boats B
WHERE NOT EXISTS ( SELECT R.bid
FROM Reserves R

WHERE R.bid = B.bid


AND R.sid = S.sid ))

Intuitively, for each sailor we check that there is no boat that has not been reserved
by this sailor.
(Q30) Find the names of sailors who are older than the oldest sailor with a rating of
10.
SELECT S.sname
FROM Sailors S
WHERE S.age > ( SELECT MAX ( S2.age )
FROM Sailors S2
WHERE S2.rating = 10 )
On instance S3, the oldest sailor with rating 10 is sailor 58, whose age is 35. The
names of older sailors are Bob, Dustin, Horatio, and Lubber. Using ALL, this query
could alternatively be written as follows:
SELECT S.sname
FROM Sailors S
WHERE S.age > ALL ( SELECT S2.age
FROM Sailors S2
WHERE S2.rating = 10 )
However, the ALL query is more error proneone could easily (and incorrectly!) use
ANY instead of ALL, and retrieve sailors who are older than some sailor with a rating
of 10. The use of ANY intuitively corresponds to the use of MIN, instead of MAX, in the
previous query.
SELECT [ DISTINCT ] select-list
FROM from-list
WHERE qualification
GROUP BY grouping-list
HAVING group-qualification

(Q33) For each red boat, find the number of reservations for this boat
It is interesting to observe that the following version of the above query is illegal:
SELECT B.bid, COUNT (*) AS sailorcount
FROM Boats B, Reserves R
WHERE R.bid = B.bid
GROUP BY B.bid
HAVING B.color = red
Even though the group-qualification B.color = red is single-valued per group, since
the grouping attribute bid is a key for Boats (and therefore determines color), SQL
disallows this query. Only columns that appear in the GROUP BY clause can appear in
the HAVING clause, unless they appear as arguments to an aggregate operator in the
HAVING clause.

OBSESR
Intersect

-> IN

SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red'
INTERSECT
SELECT S2.sname
FROM Sailors S2, Boats B2, Reserves R2
WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color= 'green';
REM Nested Query
SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color ='red'
AND S.sid IN (SELECT S2.sid
FROM Sailors S2, Boats B2, Reserves R2
WHERE S2.sid = R2.sid AND R2.bid = B2.bid
AND B2.color ='green');

reserved a red but not a gree boat"

|_> MINUS

MINUS->NOT IN
SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color = 'red'
MINUS
SELECT S2.sname
FROM Sailors S2, Boats B2, Reserves R2

WHERE S2.sid = R2.sid AND R2.bid = B2.bid AND B2.color= 'green';


SELECT S.sname
FROM Sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid AND B.color ='red'
AND S.sid NOT IN (SELECT S2.sid
FROM Sailors S2, Boats B2, Reserves R2
WHERE S2.sid = R2.sid AND R2.bid = B2.bid
AND B2.color ='green');

You might also like