Действительно трудно понять этот запрос

Следующий запрос должен вернуть "моряков, которые зарезервировали все лодки"

и вот код 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существует, что то же самое, что "моряки, которые зарезервировали все лодки"

Другие вопросы по тегам