В чем разница между использованием и включением в соединениях таблиц в MySQL?

Это

... T1 join T2 using(ID) where T2.VALUE=42 ...

такой же как

... T1 join T2 on(T1.ID=T2.ID) where T2.VALUE=42 ...

для всех типов соединений?

Насколько я понимаю using(ID), это просто сокращение от on(T1.ID=T2.ID). Это правда?


Теперь еще один вопрос:

Это то же самое, что и

... T1 join T2 on(T1.ID=T2.ID and T2.VALUE=42) ...

Я не думаю, что это правда, но почему? Как условия в предложении on взаимодействуют с соединением, а не в предложении where?


person Pyrolistical    schedule 16.12.2008    source источник
comment
Просто из интереса, какую базу данных вы используете? Я только что попробовал синтаксис USING на SQL Server, и он, похоже, не работает.   -  person Martin Brown    schedule 16.12.2008


Ответы (7)


Я не использую синтаксис USING, так как

  1. большинство моих соединений не подходят для этого (не то же имя поля, которое сопоставляется, и/или несколько совпадений в объединении) и
  2. не сразу очевидно, во что это переводится в случае с более чем двумя таблицами

т.е. предполагая 3 таблицы со столбцами «id» и «id_2», делает

T1 JOIN T2 USING(id) JOIN T3 USING(id_2)

стать

T1 JOIN T2 ON(T1.id=T2.id) JOIN T3 ON(T1.id_2=T3.id_2 AND T2.id_2=T3.id_2)

or

T1 JOIN T2 ON(T1.id=T2.id) JOIN T3 ON(T2.id_2=T3.id_2)

или что-то еще?

Выяснение этого для конкретной версии базы данных является довольно тривиальным упражнением, но я не очень уверен, что это согласовано во всех базах данных, и я не единственный человек, который должен поддерживать мой код (поэтому другие люди также должны будут знать, что это эквивалентно).

Очевидная разница между WHERE и ON заключается в том, что соединение является внешним:

Предполагая T1 с одним полем идентификатора, одной строкой, содержащей значение 1, и T2 с идентификатором и полем VALUE (одна строка, ID = 1, VALUE = 6), мы получаем:

SELECT T1.ID, T2.ID, T2.VALUE FROM T1 LEFT OUTER JOIN T2 ON(T1.ID=T2.ID) WHERE T2.VALUE=42

не дает строк, так как WHERE требуется для совпадения, тогда как

SELECT T1.ID, T2.ID, T2.VALUE FROM T1 LEFT OUTER JOIN T2 ON(T1.ID=T2.ID AND T2.VALUE=42)

даст одну строку со значениями

1, NULL, NULL

поскольку ON требуется только для сопоставления соединения, которое является необязательным из-за того, что оно внешнее.

person Cebjyre    schedule 16.12.2008

Предложение USING является сокращением для эквивалентного соединения столбцов, предполагая, что столбцы существуют в обеих таблицах с одним и тем же именем:

A JOIN B USING (column1)

A JOIN B ON A.column1=B.column1

Вы также можете назвать несколько столбцов, что делает соединения по составным ключам довольно простыми. Следующие объединения должны быть эквивалентны:

A JOIN B USING (column1, column2)

A JOIN B ON A.column1=B.column1 AND A.column2=B.column2

Обратите внимание, что USING (<columnlist>) требует наличия круглых скобок, тогда как ON <expr> не требует круглых скобок (хотя круглые скобки могут использоваться вокруг <expr>, просто они могут быть включены вокруг выражения в любом другом контексте).

Кроме того, никакие другие таблицы, присоединенные к запросу, не могут иметь столбец с таким именем, иначе запрос будет неоднозначным, и вы должны получить сообщение об ошибке.

Что касается вашего вопроса о дополнительных условиях, предполагая, что вы используете INNER JOIN, он должен логически давать тот же результат из запроса, но план оптимизации может быть затронут в зависимости от реализации СУБД. Также OUTER JOIN дает другой результат, если вы включаете условия в соединение по сравнению с предложением WHERE.

person Bill Karwin    schedule 16.12.2008
comment
Итак, как вы думаете, ON является преимуществом или особенностью языка? - person dkretz; 16.12.2008
comment
Конечно. Вам нужно ON, когда у вас есть любое выражение соединения, отличное от двух равных столбцов. Я предпочитаю использовать синтаксис SQL-92, а не помещать условия соединения в предложение WHERE. - person Bill Karwin; 16.12.2008

В результате есть разница, о которой я не вижу упоминаний в других ответах. Если вы сделаете это:

 JOIN ... ON t1.common = t2.common

тогда результирующий набор будет иметь два столбца с именами common, а именно t1.common и t2.common, и попытка сослаться на неполное имя common приведет к тому, что запрос будет отклонен как неоднозначный (даже если оба столбца обязательно содержат одно и то же значение).

Если, с другой стороны, вы делаете это:

 JOIN ... USING (common)

тогда в результирующем наборе будет только один столбец с именем common, и это будет неполное имя — ни t1.common, ни t2.common не будет присутствовать.

person Mark Reed    schedule 02.02.2017

Я считаю, что вы правы - USING (xx) - это сокращение для объединения двух столбцов с одинаковыми именами.

Что касается второго вопроса, оба запроса могут быть одинаковыми или разными в зависимости от реализации планировщика запросов, характерной для базы данных. Чтобы узнать для себя (по крайней мере, в postgres), выполните EXPLAIN SELECT ..., чтобы увидеть, как будут выполняться планы запросов.

person Elijah    schedule 16.12.2008

Если есть только одно соединение, то нет никакой разницы.

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

person dotjoe    schedule 16.12.2008

Ваша интерпретация кажется правильной. Эта статья может помочь.

Что касается второго вопроса, я не понимаю, почему результат вашего третьего примера должен отличаться от результата первых двух. Любое условие в предложении ON имеет такое же значение, как если бы оно было в предложении WHERE.

person Federico A. Ramponi    schedule 16.12.2008
comment
Нет, в зависимости от типа соединения условия в предложении ON могут иметь совсем другое значение, чем в предложении where. - person Joel Coehoorn; 16.12.2008
comment
Разве единственное слово «соединение», как в примерах, не является синонимом «внутреннего соединения»? - person Federico A. Ramponi; 16.12.2008

У вас есть ответы здесь, мне не нужно добавлять к этому. Однажды я провел тест производительности на этом, и ИСПОЛЬЗОВАНИЕ постоянно и всегда работало быстрее, чем ВКЛ. Да, я говорю о 10-20 мс :) Я говорю о MySQL

person nawfal    schedule 20.04.2012