I'm currently working on some sql tables, Here is the tables below in an image.
Sailors
sid | sname | rating | age |
---|---|---|---|
22 | Dustin | 7 | 45.0 |
29 | Brutus | 1 | 33.0 |
31 | Lubber | 8 | 55.5 |
32 | Andy | 8 | 25.5 |
58 | Rusty | 10 | 35.0 |
64 | Horatio | 7 | 35.0 |
71 | Zorba | 10 | 16.0 |
74 | Horatio | 9 | 35.0 |
85 | Art | 3 | 25.5 |
95 | Bob | 3 | 63.5 |
Reserves
sid | bid | day |
---|---|---|
22 | 101 | 10/10/98 |
22 | 102 | 10/10/98 |
22 | 103 | 10/8/98 |
22 | 104 | 10/7/98 |
31 | 102 | 11/10/98 |
31 | 103 | 11/6/98 |
31 | 104 | 11/12/98 |
64 | 101 | 9/5/98 |
64 | 102 | 9/8/98 |
74 | 103 | 9/8/98 |
Boats
bid | bname | bcolor |
---|---|---|
101 | Interlake | blue |
102 | Interlake | red |
103 | Clipper | green |
104 | Marine | red |
So, I want to select a person in table Sailors who had reserved all boats from table boats, which is Dustin.
My first thought on the code is
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 b.color='green' AND b.color='blue';
But, the function above will keep increasing if I add the new boats with a different colors.
My question is, are there any shorter way to call the person without stating the boat one by one? Is there any shorter version to do this?
Thank you!
CodePudding user response:
The approach I'd take would be to select all sid
values from table_reserves
that have a distinct count of bid
equal to the rowcount of the boats
table. I don't have your schema prepared, but it'd be something like this:
with cte AS (
SELECT
sid,
COUNT(DISTINCT bid) AS unique_boat_count
FROM reserves r
HAVING COUNT(DISTINCT bid) = (
SELECT COUNT(*)
FROM boats
)
)
select
s.sname
FROM cte
INNER JOIN sailors s
ON s.sid = cte.sid
CodePudding user response:
Start with this:
SELECT s.sid
FROM Sailors
INNER JOIN Reserves r on r.sid = s.sid
GROUP BY s.ID
HAVING COUNT(DISTINCT r.bid) =
(SELECT count(distinct bid) from boats)
What we're doing is matching the count of total unique boats registered with the count of total votes possible. If you need more than just the sid
value you can JOIN back to the Sailors
table again.
Do NOT use the old FROM A,B
join syntax for this, as you did in the original question. That syntax has been obsolete for more than 25 years now. Today, you should pretty much always specify the JOIN
keyword.