2011-01-24 6 views
13

Мне любопытно, почему мы должны использовать LEFT JOIN, так как мы можем использовать запятые, чтобы выбрать несколько таблиц.Левое соединение или выбор из нескольких таблиц с помощью запятой (,)

В чем разница между LEFT JOIN и с запятыми, чтобы выбрать несколько таблиц.

Какой из них быстрее?

Вот мой код:

SELECT mw.*, 
      nvs.* 
    FROM mst_words mw 
LEFT JOIN (SELECT no as nonvs, 
        owner, 
        owner_no, 
        vocab_no, 
        correct 
      FROM vocab_stats 
      WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0) 
     AND mw.level = 1 

... и:

SELECT * 
    FROM vocab_stats vs, 
     mst_words mw 
WHERE mw.no = vs.vocab_no 
    AND vs.correct > 0 
    AND mw.level = 1 
    AND vs.owner = 1111 
+1

Первый пример ВЕРСИЯ (в данном случае, ВЛЕВО) ПРИСОЕДИНЯЙТЕСЬ (ANSI-92), последний является ВХОДНЫМ СОЕДИНЕНИЕМ (ANSI-89, который не поддерживает соединения OUTER). Если всегда есть запись, связывающая две таблицы, маловероятно, что они вернут те же результаты. –

+0

@OMG Последний «не» INNER JOIN. Это ближе к CROSS JOIN по определению, так как это декартово произведение. – RichardTheKiwi

+1

Синтаксис ANSI-89 ... план объяснения идентичен использованию ... ... FROM VOCAB_STATS s JOIN MSTWORDS w ON w.no = v.vocab_no ... '. Опять же - ** нет, второй запрос не возвращает декартова произведение **. –

ответ

3

Прежде всего, чтобы быть полностью эквивалентны, то первый запрос должен быть написан

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, но это не обсуждается здесь.
0

Разделяя РЕГИСТРИРУЙТЕСЬ от WHERE позволяет легко читать, поскольку логика не может присоединиться путайте с условиями WHERE. Он также, как правило, будет быстрее, так как серверу не нужно будет выполнять два отдельных запроса и объединить результаты.

Два примера, которые вы указали, на самом деле не эквивалентны, так как вы включили подзапрос в первом примере. Это лучший пример:..

SELECT vs.*, mw.* 
FROM vocab_stats vs, mst_words mw 
LEFT JOIN vocab_stats vs ON mw.no = vs.vocab_no 
WHERE vs.correct > 0 
AND mw.level = 1 
AND vs.owner = 1111 
+0

SQL недействителен – RichardTheKiwi

+0

Спасибо, я просто удалил опечатку. – Bazmatiq

Смежные вопросы