Прежде всего, чтобы быть полностью эквивалентны, то первый запрос должен быть написан
SELECT mw.*,
nvs.*
FROM mst_words mw
LEFT JOIN (SELECT *
FROM vocab_stats
WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no
WHERE (nvs.correct > 0)
AND mw.level = 1
Так что МВТ * и NVS * вместе производят один и тот же набор как сингулярность второго запроса *. Запрос, который вы написали, может использовать INNER JOIN, так как он включает фильтр на nvs.correct.
Общий вид
TABLEA LEFT JOIN TABLEB ON <CONDITION>
attempts
найти записи TableB на основе состояния. Если сбой завершается, результаты TABLEA сохраняются, при этом все столбцы из TableB равны NULL. В отличие от
TABLEA INNER JOIN TABLEB ON <CONDITION>
также attempts
, чтобы найти записи TableB на основе состояния. Однако, когда сбой, конкретная запись из таблицы А удаляется из выходного результирующего набора.
Стандарт ANSI для CROSS JOIN создает между двумя таблицами Cartesian product.
TABLEA CROSS JOIN TABLEB
-- # or in older syntax, simply using commas
TABLEA, TABLEB
Намерение синтаксиса является то, что каждая строка в TABLEA присоединяется к каждой строке в TableB. Таким образом, 4 строки в A и 3 строки в B производят 12 строк вывода. При сопряжении с условиями в предложении WHERE он иногда вызывает одно и то же поведение INNER JOIN, поскольку они выражают одно и то же (условие между A и B => сохранить или нет). Тем не менее, это намного яснее, когда вы читаете о намерении, когда вы используете INNER JOIN вместо запятых.
Производительность, большинство СУБД будут обрабатывать ЛЕВОЕ соединение быстрее, чем INNER JOIN. Обозначение запятой может привести к тому, что системы баз данных неверно истолковывают намерение и создают плохой план запроса, поэтому еще один плюс для нотации SQL92.
Зачем нам нужно ВЛЕВО? Если объяснение LEFT JOIN выше все еще недостаточно (сохраняйте записи в A без совпадений в B), тогда подумайте, что для достижения того же вам понадобится сложный UNION между двумя наборами, используя старую запятую для достижения того же эффект. Но, как указано выше,, это не относится к вашему примеру, который действительно является INNER JOIN, скрывающимся за LEFT JOIN.
Примечания:
- ПРАВИЛЬНЫЙ РЕГИСТРИРУЙТЕСЬ такое же, как LEFT, за исключением того, что она начинается с TableB (правая сторона) вместо А.
- направо и налево JOINS оба OUTER соединения. Слово OUTER необязательно, то есть оно может быть записано как
LEFT OUTER JOIN
.
- Третий тип соединения OUTER - это FULL OUTER, но это не обсуждается здесь.
Первый пример ВЕРСИЯ (в данном случае, ВЛЕВО) ПРИСОЕДИНЯЙТЕСЬ (ANSI-92), последний является ВХОДНЫМ СОЕДИНЕНИЕМ (ANSI-89, который не поддерживает соединения OUTER). Если всегда есть запись, связывающая две таблицы, маловероятно, что они вернут те же результаты. –
@OMG Последний «не» INNER JOIN. Это ближе к CROSS JOIN по определению, так как это декартово произведение. – RichardTheKiwi
Синтаксис ANSI-89 ... план объяснения идентичен использованию ... ... FROM VOCAB_STATS s JOIN MSTWORDS w ON w.no = v.vocab_no ... '. Опять же - ** нет, второй запрос не возвращает декартова произведение **. –