Действительно трудно понять этот запрос
Следующий запрос должен вернуть "моряков, которые зарезервировали все лодки"
и вот код MySQL
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS
((SELECT B.bid
FROM Boats B)
Except
(SELECT R.bid
FROM Reserves R
WHERE R.sid = S.sid))
И я просто... не знаю, как это прочитать. Я понимаю, что подзапрос, следующий за "НЕ СУЩЕСТВУЕТ", должен возвращать идентификатор лодки (bid) для всех записей в таблице Boats. Таким образом, запрос, следующий за исключением, должен возвращать идентификаторы лодок для всех лодок, которые были зарезервированы... так что это означает, что если есть кто-то, кто зарезервировал все лодки, ничего не должно возвращаться, то есть NOT EXISTS будет иметь значение true и будет просто назовите имя этого моряка? Я думаю, что это последняя часть, которая смущает меня... как это в конечном итоге вернуть имя моряка?
2 ответа
У нас есть несколько лодок, которые могут быть зарезервированы моряками, моряки зарегистрированы, и мы их знаем, поэтому структура таблиц такова:
[Table: Boats] [Table: Sailors] [Table: Reserves]
+-----+--------+ +-----+----------+ +-----+-----+-----+
| bid | bname | | sid | sname | | rid | bid | sid |
+-----+--------+ +-----+----------+ +-----+-----+-----+
| 1 | Boat 1 | | 1 | Sailor 1 | | 1 | 1 | 1 |
| 2 | Boat 2 | | 2 | Sailor 2 | | 2 | 2 | 3 |
| 3 | Boat 3 | | 3 | Sailor 3 | +-----+-----+-----+
+-----+--------+ +-----+----------+
В приведенных выше данных, когда вам нужно знать, какие лодки не зарезервированы; Вы можете использовать ниже запрос, который даст вам ставку => 3:
SELECT B.bid FROM Boats B
EXCEPT
SELECT R.bid FROM Reserves R;
И когда вам нужно знать, какие лодки (никогда) не зарезервированы моряком; Вы можете использовать запрос ниже, который даст вам ставку => [1, 3] для sid = 3:
SELECT B.bid FROM Boats B
EXCEPT
SELECT R.bid FROM Reserves R WHERE R.[sid] = 3;
И когда моряк резервирует все лодки, вышеупомянутый запрос не будет иметь никакого результата, поэтому NOT EXISTS(<above query>)
будет правдой. Теперь вы можете использовать вышеуказанный запрос, чтобы найти моряков, которые резервируют все лодки следующим образом:
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS (
SELECT B.bid FROM Boats B
EXCEPT
SELECT R.bid FROM Reserves R
WHERE R.[sid] = S.[sid]);
Так что если данные Reserves
стать чем-то вроде этого:
[Table: Reserves]
+-----+-----+-----+
| rid | bid | sid |
+-----+-----+-----+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
+-----+-----+-----+
Ваш запрос даст результат Sailor 1
;).
Больше информации: EXCEPT
возвращает отдельные строки из левого входного запроса, которые не выводятся правым входным запросом. EXISTS
: Указывает подзапрос для проверки существования строк.
Вы можете преобразовать SQL, подвыбор
(SELECT B.bid
FROM Boats B)
Except
(SELECT R.bid
FROM Reserves R
WHERE R.sid = S.sid)
должен быть таким же, как
(SELECT B.bid
FROM Boats B
WHERE B.sid <> S.sid)
Если вы замените часть в основной SQL, вы получите
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS
(SELECT B.bid
FROM Boats B
WHERE B.sid <> S.sid)
Выбирайте только тех моряков, для которых нет лодок с другими sid
существует, что то же самое, что "моряки, которые зарезервировали все лодки"