Для простоты предположим, что все соответствующие поля NOT NULL
.
Ты можешь сделать:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1, table2
WHERE
table1.foreignkey = table2.primarykey
AND (some other conditions)
Или еще:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1 INNER JOIN table2
ON table1.foreignkey = table2.primarykey
WHERE
(some other conditions)
Эти два работают одинаково MySQL
?
sql
mysql
join
inner-join
JCCyC
источник
источник
Ответы:
INNER JOIN
это синтаксис ANSI, который вы должны использовать.Как правило, он считается более читабельным, особенно когда вы объединяете множество таблиц.
Он также может быть легко заменен
OUTER JOIN
всякий раз, когда возникает необходимость.WHERE
Синтаксис ориентирован более реляционная модель.Результат двух таблиц
JOIN
ed является декартово произведение таблиц, к которым применен фильтр, который выбирает только те строки с сопоставлением соединяющих столбцов.Это легче увидеть с
WHERE
синтаксиса.Что касается вашего примера, в MySQL (и в SQL в целом) эти два запроса являются синонимами.
Также обратите внимание, что MySQL также имеет
STRAIGHT_JOIN
пункт.Используя этот пункт, вы можете контролировать
JOIN
порядком: какая таблица сканируется во внешнем цикле, а какая во внутреннем цикле.Вы не можете контролировать это в MySQL, используя
WHERE
синтаксис.источник
Oracle
,SQL Server
,MySQL
иPostgreSQL
- да. Для других систем, наверное, тоже, но вам лучше проверить.WHERE
разделе также в стандарте ANSI.@Bill Karwin
:JOIN
Ключевое слово не было частью проприетарных стандартов до недавнего времени, что может показаться. Он вошелOracle
только в версии9
иPostgreSQL
в версии7.2
(обе выпущены в2001
). Внешний вид этого ключевого слова был частьюANSI
стандартного принятия, и именно поэтому это ключевое слово обычно ассоциируется с нимANSI
, несмотря на то, что последнее поддерживает также запятую как синоним дляCROSS JOIN
.WHERE
предложении (как вы сказали, соединение без условий эквивалентно перекрестному соединению). ANSI SQL-92 добавилJOIN
ключевое слово и связанный с ним синтаксис, но синтаксис в стиле запятых все еще поддерживается для обеспечения обратной совместимости.Другие отметили, что это
INNER JOIN
помогает читабельности человека, и это, я согласен, главный приоритет.Позвольте мне попытаться объяснить, почему синтаксис объединения более читабелен.
Основной
SELECT
запрос таков:Предложение
SELECT
говорит нам, что мы получаем обратно;FROM
пункт говорит нам , где мы получаем его от, иWHERE
пункт говорит нам , которые из них мы получаем.JOIN
это утверждение о таблицах, как они связаны друг с другом (концептуально, фактически, в одну таблицу).Любые элементы запроса, которые управляют таблицами - откуда мы берем материал - семантически принадлежат
FROM
предложению (и, конечно, именно тудаJOIN
идут элементы). Ввод Соединительные элементы вWHERE
пункте смешивает , который и где-с , именно поэтомуJOIN
предпочтительным является синтаксис.источник
Применение условных операторов в ON / WHERE
Здесь я объяснил о шагах обработки логического запроса.
Ссылка: Внутри Microsoft® SQL Server ™ 2005 T-SQL Querying
Издатель: Microsoft Press
Pub Дата: 7 марта 2006 г.
Печать ISBN-10: 0-7356-2313-9
Печать ISBN-13: 978-0-7356-2313-2
Страницы: 640
Внутри Microsoft® SQL Server ™ 2005 T-SQL-запросов
Первый заметный аспект SQL, отличающийся от других языков программирования, - это порядок обработки кода. В большинстве языков программирования код обрабатывается в том порядке, в котором он написан. В SQL первое предложение, которое обрабатывается, это предложение FROM, в то время как предложение SELECT, которое появляется первым, обрабатывается почти последним.
Каждый шаг генерирует виртуальную таблицу, которая используется в качестве входных данных для следующего шага. Эти виртуальные таблицы недоступны для вызывающей стороны (клиентское приложение или внешний запрос). Только таблица, созданная на последнем шаге, возвращается вызывающей стороне. Если в запросе не указано определенное предложение, соответствующий шаг просто пропускается.
Краткое описание этапов обработки логических запросов
Не беспокойтесь, если описание шагов пока не имеет особого смысла. Они предоставляются в качестве ссылки. Разделы, которые следуют после примера сценария, будут охватывать шаги более подробно.
FROM: декартово произведение (перекрестное соединение) выполняется между первыми двумя таблицами в предложении FROM, и в результате создается виртуальная таблица VT1.
ON: фильтр ON применяется к VT1. Только строки, для которых
<join_condition>
TRUE, вставляются в VT2.OUTER (соединение): если указано OUTER JOIN (в отличие от CROSS JOIN или INNER JOIN), строки из сохраненной таблицы или таблиц, для которых не найдено совпадение, добавляются в строки из VT2 в качестве внешних строк, генерируя VT3. Если в предложении FROM появляется более двух таблиц, шаги с 1 по 3 применяются повторно между результатом последнего соединения и следующей таблицей в предложении FROM, пока не будут обработаны все таблицы.
ГДЕ: ГДЕ фильтр применяется к VT3. Только строки, для которых
<where_condition>
TRUE, вставляются в VT4.GROUP BY: строки из VT4 упорядочены в группы на основе списка столбцов, указанного в предложении GROUP BY. VT5 генерируется.
КУБ | ROLLUP: супергруппы (группы групп) добавляются в строки из VT5, генерируя VT6.
HAVING: фильтр HAVING применяется к VT6. Только группы, для которых
<having_condition>
TRUE, вставляются в VT7.SELECT: список SELECT обрабатывается, генерируя VT8.
DISTINCT: повторяющиеся строки удаляются из VT8. VT9 генерируется.
ORDER BY: строки из VT9 сортируются в соответствии со списком столбцов, указанным в предложении ORDER BY. Курсор генерируется (VC10).
TOP: указанное количество или процент строк выбирается с начала VC10. Таблица VT11 генерируется и возвращается вызывающей стороне.
Следовательно, (INNER JOIN) ON будет фильтровать данные (количество данных VT будет само здесь уменьшаться) перед применением предложения WHERE. Последующие условия соединения будут выполняться с отфильтрованными данными, что повышает производительность. После этого только условие WHERE будет применять условия фильтра.
(Применение условных операторов в ON / WHERE не будет иметь большого значения в нескольких случаях. Это зависит от количества таблиц, к которым вы присоединились, и количества строк, доступных в каждой из таблиц объединения)
источник
Синтаксис неявного соединения ANSI более старый, менее очевидный и не рекомендуется.
Кроме того, реляционная алгебра обеспечивает взаимозаменяемость предикатов в
WHERE
предложении иINNER JOIN
, таким образом, дажеINNER JOIN
запросы сWHERE
предложениями могут иметь предикаты, переупорядоченные оптимизатором.Я рекомендую вам писать запросы наиболее читабельным способом.
Иногда это включает в себя создание
INNER JOIN
относительно «неполных» и включение некоторых критериевWHERE
просто для того, чтобы сделать списки критериев фильтрации более легкими в обслуживании.Например, вместо:
Написать:
Но это зависит, конечно.
источник
Неявные объединения (это то, что называется вашим первым запросом) становятся намного более запутанными, трудными для чтения и сложными для обслуживания, когда вам нужно начать добавлять больше таблиц в ваш запрос. Представьте себе, что вы выполняете тот же запрос и тип соединения для четырех или пяти разных таблиц ... это кошмар.
Использование явного соединения (ваш второй пример) намного удобнее для чтения и обслуживания.
источник
Я также укажу, что использование старого синтаксиса более подвержено ошибкам. Если вы используете внутренние объединения без предложения ON, вы получите синтаксическую ошибку. Если вы используете более старый синтаксис и забудете одно из условий соединения в предложении where, вы получите перекрестное соединение. Разработчики часто исправляют это, добавляя отдельное ключевое слово (а не исправляя соединение, потому что они все еще не осознают, что само соединение нарушено), которое может решить проблему, но значительно замедлит запрос.
Кроме того, для техобслуживания, если у вас есть перекрестное соединение в старом синтаксисе, как специалист по сопровождению узнает, что вы хотели бы иметь его (есть ситуации, когда необходимо перекрестное объединение) или если это был несчастный случай, который следует исправить?
Позвольте мне указать вам на этот вопрос, чтобы понять, почему неявный синтаксис плох, если вы используете левые соединения. Sybase * = к стандарту Ansi с 2 разными внешними таблицами для одной внутренней таблицы
Плюс (личная напыщенная речь здесь), стандарту, использующему явные объединения, более 20 лет, что означает, что неявный синтаксис объединения был устаревшим в течение этих 20 лет. Вы бы написали код приложения, используя синтаксис, который устарел в течение 20 лет? Почему вы хотите написать код базы данных?
источник
HAVING
"устаревшего", так как SQL начал поддерживать производные таблицы. Я также заметил, что вы не используете,NATURAL JOIN
хотя я бы сказал, что онINNER JOIN
устарел. Да, у вас есть свои причины (нет необходимости повторять их здесь!): Я хочу сказать, что те, кому нравится использовать более старый синтаксис, тоже имеют свои причины, и относительный возраст синтаксиса практически не имеет значения.Они имеют различный человекочитаемый смысл.
Однако, в зависимости от оптимизатора запросов, они могут иметь одинаковое значение для машины.
Вы должны всегда кодировать, чтобы быть читаемым.
То есть, если это встроенные отношения, используйте явное соединение. если вы сопоставляете слабо связанные данные, используйте предложение where.
источник
Стандарт SQL: 2003 изменил некоторые правила приоритета, поэтому оператор JOIN имеет приоритет над соединением «запятая». Это может фактически изменить результаты вашего запроса в зависимости от того, как он настроен. Это вызывает некоторые проблемы у некоторых людей, когда MySQL 5.0.12 перешел на соблюдение стандарта.
Так что в вашем примере ваши запросы будут работать одинаково. Но если вы добавили третью таблицу: SELECT ... FROM table1, table2 ПРИСОЕДИНЯЙТЕСЬ к table3 ON ... WHERE ...
До MySQL 5.0.12 сначала объединялись table1 и table2, затем table3. Теперь (5.0.12 и далее) сначала объединяются table2 и table3, затем table1. Это не всегда меняет результаты, но может и вы можете даже не осознавать этого.
Я никогда больше не использую синтаксис "запятая", выбирая второй пример. В любом случае, это намного более читабельно, условия JOIN связаны с JOIN, а не разделены на отдельный раздел запроса.
источник
Я знаю, что вы говорите о MySQL, но в любом случае: в Oracle 9 явные объединения и неявные объединения генерируют разные планы выполнения. AFAIK, который был решен в Oracle 10+: такой разницы больше нет.
источник
Синтаксис соединения ANSI определенно более переносим.
Я собираюсь обновить Microsoft SQL Server и упомянуть, что синтаксис = * и * = для внешних объединений в SQL Server не поддерживается (без режима совместимости) для SQL Server 2005 и более поздних версий.
источник
*=
и=*
никогда не были ANSI и никогда не были хорошей нотацией. Вот почему ON был необходим - для ВНЕШНИХ СОЕДИНЕНИЙ в отсутствие подвыборов (которые были добавлены в то же время, так что они на самом деле не нужны в CROSS & INNER JOIN.)Если вы часто программируете динамические хранимые процедуры, вы влюбитесь в свой второй пример (используя where). Если у вас есть различные входные параметры и много морфов, то это единственный способ. В противном случае они оба будут выполнять один и тот же план запросов, поэтому в классических запросах явно нет явных различий.
источник