Если мы не в зависимости от поведения, которое мы получили бы, если подзапрос в NOT IN (subquery)
возвратит значение NULL для `studentid` ...
(Если подзапрос возвращает NULL, то НЕ Сравнение IN никогда не будет оцениваться до TRUE для любой строки, поэтому внешний запрос не будет возвращать никакие строки.)
Возможно, существует какая-то гарантия того, что `studentid` никогда не будет NULL, как и его определенные чтобы быть НЕ НАЙДЕННЫМ, или это ПЕРВИЧНЫЙ КЛЮЧ ... но мы этого не видим. И в этом подзапросе нет условия studentid IS NOT NULL
, поэтому мы должны предвидеть поведение, которое произойдет, если подзапрос вернет NULL.
Если мы не заинтересованы в сохранении такого поведения,
то NOT IN (subquery)
может быть выражено как antijoin узор.
SELECT need.studentid
, need.firstname
, need.lastname
, need.courseid
FROM (SELECT student.studentid
, student.firstname
, student.lastname
, enrollment.courseid
FROM prereq
LEFT
JOIN enrollment
ON prereq.courseid = enrollment.courseid
LEFT
JOIN student
ON enrollment.studentid = student.studentid
) need
LEFT
JOIN enrollment aj
ON aj.studentid = need.studentid
AND NOT (aj.grade LIKE '%F' OR aj.grade IS NULL OR aj.grade LIKE 'N')
WHERE aj.studentid IS NULL
анти-присоединиться модель выглядит как внешнее соединение (вернуть все строки, с одной стороны, а также соответствующие строки из другого), и условие в ИНЕКЕ, что исключает все строки, которые имели матч.
Это работает, потому что гарантируется, что at.studentid
не имеет значения NULL для любых найденных совпадающих строк. Для любой строки из need
, у которой не было соответствующей строки в aj
, эти строки будут иметь значение NULL для столбцов с aj
. (Это то, что в основном заключается в внешнем соединении ... вставляет строку значений NULL, чтобы служить в качестве строки соответствия заполнителя для операции соединения.)
Для условного теста в предложении WHERE все, что нам нужно сделать, это проверить для значений NULL в одном из столбцов от aj
, которые гарантированно будут не равными NULL. Если бы мы знали, что это такое, мы могли бы обратиться к ПЕРВИЧНОМУ КЛЮЧУ таблицы. Мы можем использовать столбец studentid
, потому что любая строка, которая удовлетворяет сопоставлению равенства в условии соединения, гарантируется, что она не является NULL.)
SQL-антияпон можно перевести в реляционную алгебру.
Эквивалентный результат может быть возвращен без встроенного представления.
SELECT student.studentid
, student.firstname
, student.lastname
, enrollment.courseid
FROM prereq
LEFT
JOIN enrollment
ON prereq.courseid = enrollment.courseid
LEFT
JOIN student
ON enrollment.studentid = student.studentid
LEFT
JOIN enrollment aj
ON aj.studentid = student.studentid
AND NOT (aj.grade LIKE '%F' OR aj.grade IS NULL OR aj.grade LIKE 'N')
WHERE aj.studentid IS NULL
Перед тем, как преобразование в РА, так как 'NOT в' часть включает в себя таблицу, в которой уже имеются ссылки в объединение в первых скобках, вероятно, можно преобразовать выражение фильтра из' NOT IN (SELECT .. .' часть в состояние фильтра прямо на соединение. –
Ну, не могли бы вы дать мне подсказку, как это сделать? –