Sql cross join пример: Оператор SQL CROSS JOIN: примеры, синтаксис

Содержание

Оператор SQL CROSS JOIN: примеры, синтаксис

Оператор SQL CROSS JOIN формирует таблицу перекрестным соединением (декартовым произведением) двух таблиц. При использовании оператора SQL CROSS JOIN каждая строка левой таблицы сцепляется с каждой строкой правой таблицы. В результате получается таблица со всеми возможными сочетаниями строк обеих таблиц.

Оператор SQL CROSS JOIN имеет следующий синтаксис:

SELECT
    column_names [,... n]
FROM
    Table_1 CROSS JOIN Table_2

Обратите внимание, что в операторе за ненадобностью отсутствует условие (ON).


Примеры оператора SQL CROSS JOIN. Имеются две таблицы:

Authors — содержит в себе информацию об авторах книг:

AuthorIDAuthorName
1Bruce Eckel
2Robert Lafore
3Andrew Tanenbaum

Books — содержит в себе информацию о названии книг:

BookIDBookName
3Modern Operating System
1Thinking in Java
3Computer Architecture
4Programming in Scala

В таблице Books поле BookID являются внешним ключом и ссылаются на таблицу Authors.

Пример 1. Произвести декартово произведение обеих таблиц с помощью оператора SQL CROSS JOIN:

SELECT *
FROM Authors CROSS JOIN Books

Результирующая таблица будет выглядеть следующим образом:

Authors.AuthorIDAuthors.AuthorNameBooks.BookIDBooks.BookName
1Bruce Eckel3Modern Operating System
1Bruce Eckel1Thinking in Java
1Bruce Eckel3Computer Architecture
1Bruce Eckel4Programming in Scala
2Robert Lafore3Modern Operating System
2Robert Lafore1Thinking in Java
2Robert Lafore3Computer Architecture
2Robert Lafore4Programming in Scala
3Andrew Tanenbaum3Modern Operating System
3Andrew Tanenbaum1Thinking in Java
3Andrew Tanenbaum3Computer Architecture
3Andrew Tanenbaum4Programming in Scala

Cross join sql пример — Вэб-шпаргалка для интернет предпринимателей!

Продолжаем изучать основы SQL, и пришло время поговорить о простых объединениях JOIN. И сегодня мы рассмотрим, как объединяются данные по средствам операторов LEFT JOIN, RIGHT JOIN, CROSS JOIN и INNER JOIN, другими словами, научимся писать запросы, которые объединяют данные, и как обычно изучать все это будем на примерах.

Объединения JOIN очень важны в SQL, так как без умения писать запросы с объединением данных разных объектов, просто не обойтись программисту SQL, да и просто админу который время от времени выгружает какие-то данные из базы данных, поэтому это относится к основам SQL и каждый человек, который имеет дело с SQL, должен иметь представление, что это такое.

Примечание! Все примеры будем писать в Management Studio SQL Server 2008.

Мы с Вами уже давно изучаем основы SQL, и если вспомнить начинали мы с оператора select, и вообще было уже много материала на этом сайте по SQL, например:

И много другого, даже уже рассматривали объединения union и union all, но, так или иначе, более подробно именно об объединениях join мы с Вами не разговаривали, поэтому сегодня мы восполним этот пробел в наших знаниях.

И начнем мы как обычно с небольшой теории.

Объединения JOIN — это объединение двух или более объектов базы данных по средствам определенного ключа или ключей или в случае cross join и вовсе без ключа. Под объектами здесь подразумевается различные таблицы, представления (views), табличные функции или просто подзапросы sql, т.е. все, что возвращает табличные данные.

Объединение SQL LEFT и RIGHT JOIN

LEFT JOIN – это объединение данных по левому ключу, т.е. допустим, мы объединяем две таблицы по left join, и это значит что все данные из второй таблицы подтянутся к первой, а в случае отсутствия ключа выведется NULL значения, другими словами выведутся все данные из левой таблицы и все данные по ключу из правой таблицы.

RIGHT JOIN – это такое же объединение как и Left join только будут выводиться все данные из правой таблицы и только те данные из левой таблицы в которых есть ключ объединения.

Теперь давайте рассматривать примеры, и для начала создадим две таблицы:

Вот такие простенькие таблицы, И я для примера заполнил их вот такими данными:

Теперь давайте напишем запрос с объединением этих таблиц по ключу number, для начала по LEFT:

Как видите, здесь данные из таблицы t1 вывелись все, а данные из таблицы t2 не все, так как строки с number = 4 там нет, поэтому и вывелись NULL значения.

А что будет, если бы мы объединяли по средствам right join, а было бы вот это:

Другими словами, вывелись все строки из таблицы t2 и соответствующие записи из таблицы t1, так как все те ключи, которые есть в таблице t2, есть и в таблице t1, и поэтому у нас нет NULL значений.

Объединение SQL INNER JOIN

Inner join – это объединение когда выводятся все записи из одной таблицы и все соответствующие записи из другой таблице, а те записи которых нет в одной или в другой таблице выводиться не будут, т.е. только те записи которые соответствуют ключу. Кстати сразу скажу, что inner join это то же самое, что и просто join без Inner. Пример:

А теперь давайте попробуем объединить наши таблицы по двум ключам, для этого немного вспомним, как добавлять колонку в таблицу и как обновить данные через update, так как в наших таблицах всего две колонки, и объединять по текстовому полю как-то не хорошо. Для этого добавим колонки:

Обновим наши данные, просто проставим в колонку number2 значение 1:

И давайте напишем запрос с объединением по двум ключам:

И результат будет таким же, как и в предыдущем примере:

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

Запрос тот же самый, а вот результат:

Как видите, по второму ключу у нас одна строка не вывелась.

Объединение SQL CROSS JOIN

CROSS JOIN – это объединение SQL по которым каждая строка одной таблицы объединяется с каждой строкой другой таблицы. Лично у меня это объединение редко требуется, но все равно иногда требуется, поэтому Вы также должны уметь его использовать. Например, в нашем случае получится, конечно, не понятно что, но все равно давайте попробуем, тем более синтаксис немного отличается:

Здесь у нас каждой строке таблицы test_table соответствует каждая строка из таблицы test_table_2, т.е. в таблице test_table у нас 4 строки, а в таблице test_table_2 3 строки 4 умножить 3 и будет 12, как и у нас вывелось 12 строк.

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

Как видите, я здесь объединяю и по left и по right и по inner просто, для того чтобы это было наглядно.

С объединениями я думаю достаточно, тем более ничего сложного в них нет. Но на этом изучение SQL не закончено в следующих статьях мы продолжим, а пока тренируйтесь и пишите свои запросы. Удачи!

JOIN — оператор языка SQL, который является реализацией операции соединения реляционной алгебры. Входит в предложение FROM операторов SELECT, UPDATE и DELETE.

Операция соединения, как и другие бинарные операции, предназначена для обеспечения выборки данных из двух таблиц и включения этих данных в один результирующий набор. Отличительными особенностями операции соединения являются следующие:

  • в схему таблицы-результата входят столбцы обеих исходных таблиц (таблиц-операндов), то есть схема результата является «сцеплением» схем операндов;
  • каждая строка таблицы-результата является «сцеплением» строки из одной таблицы-операнда со строкой второй таблицы-операнда.

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

При необходимости соединения не двух, а нескольких таблиц, операция соединения применяется несколько раз (последовательно).

SQL-операция JOIN является реализацией операции соединения реляционной алгебры только в некотором приближении, поскольку в реляционной модели данных соединение выполняется над отношениями, которые являются множествами, а в SQL — над таблицами, которые являются мультимножествами. Результаты операций тоже, в общем случае, различны: в реляционной алгебре результат соединения даёт отношение (множество), а в SQL — таблицу (мультимножество).

Содержание

Описание оператора [ править | править код ]

В большинстве СУБД при указании слов LEFT , RIGHT , FULL слово OUTER можно опустить. Слово INNER также в большинстве СУБД можно опустить.

В общем случае СУБД при выполнении соединения проверяет условие (предикат) condition. Если названия столбцов, по которым происходит соединение таблиц, совпадают, то вместо ON можно использовать USING . Для CROSS JOIN условие не указывается.

Для перекрёстного соединения (декартова произведения) CROSS JOIN в некоторых реализациях SQL используется оператор «запятая» (,):

Виды оператора JOIN [ править | править код ]

Для дальнейших пояснений будут использоваться следующие таблицы:

City (Города)

IdName
1Москва
2Санкт-Петербург
3Казань
Person (Люди)

NameCityId
Андрей1
Леонид2
Сергей1
Григорий4

INNER JOIN [ править | править код ]

Оператор внутреннего соединения INNER JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Каждая строка одной таблицы сопоставляется с каждой строкой второй таблицы, после чего для полученной «соединённой» строки проверяется условие соединения (вычисляется предикат соединения). Если условие истинно, в таблицу-результат добавляется соответствующая «соединённая» строка.

Описанный алгоритм действий является строго логическим, то есть он лишь объясняет результат, который должен получиться при выполнении операции, но не предписывает, чтобы конкретная СУБД выполняла соединение именно указанным образом. Существует несколько способов реализации операции соединения, например, соединение вложенными циклами (англ. inner loops join ), соединение хешированием (англ. hash join ), соединение слиянием (англ. merge join ). Единственное требование состоит в том, чтобы любая реализация логически давала такой же результат, как при применении описанного алгоритма.

Person.NamePerson.CityIdCity.IdCity.Name
Андрей11Москва
Леонид22Санкт-Петербург
Сергей11Москва

OUTER JOIN [ править | править код ]

Соединение двух таблиц, в результат которого обязательно входят все строки либо одной, либо обеих таблиц.

LEFT OUTER JOIN [ править | править код ]

Оператор левого внешнего соединения LEFT OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение левой и правой таблиц по предикату (условию) p.

  1. В результат включается внутреннее соединение ( INNER JOIN ) левой и правой таблиц по предикату p.
  2. Затем в результат добавляются те строки левой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие правой таблице, заполняются значениями NULL .
Person.NamePerson.CityIdCity.IdCity.Name
Андрей11Москва
Леонид22Санкт-Петербург
Сергей11Москва
Григорий4NULLNULL
RIGHT OUTER JOIN [ править | править код ]

Оператор правого внешнего соединения RIGHT OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение левой и правой таблиц по предикату (условию) p.

  1. В результат включается внутреннее соединение ( INNER JOIN ) левой и правой таблиц по предикату p.
  2. Затем в результат добавляются те строки правой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие левой таблице, заполняются значениями NULL .
Person.NamePerson.CityIdCity.IdCity.Name
Андрей11Москва
Сергей11Москва
Леонид22Санкт-Петербург
NULLNULL3Казань
FULL OUTER JOIN [ править | править код ]

Оператор полного внешнего соединения FULL OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение первой и второй таблиц по предикату (условию) p. Слова «первой» и «второй» здесь не обозначают порядок в записи выражения (который неважен), а используются лишь для различения таблиц.

  1. В результат включается внутреннее соединение ( INNER JOIN ) первой и второй таблиц по предикату p.
  2. В результат добавляются те строки первой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие второй таблице, заполняются значениями NULL .
  3. В результат добавляются те строки второй таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие первой таблице, заполняются значениями NULL .
Person.NamePerson.CityIdCity.IdCity.Name
Андрей11Москва
Сергей11Москва
Леонид22Санкт-Петербург
NULLNULL3Казань
Григорий4NULLNULL

CROSS JOIN [ править | править код ]

Оператор перекрёстного соединения, или декартова произведения CROSS JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Каждая строка одной таблицы соединяется с каждой строкой второй таблицы, давая тем самым в результате все возможные сочетания строк двух таблиц.

Person.NamePerson.CityIdCity.IdCity.Name
Андрей11Москва
Андрей12Санкт-Петербург
Андрей13Казань
Леонид21Москва
Леонид22Санкт-Петербург
Леонид23Казань
Сергей11Москва
Сергей12Санкт-Петербург
Сергей13Казань
Григорий41Москва
Григорий42Санкт-Петербург
Григорий43Казань

Если в предложении WHERE добавить условие соединения (предикат p), то есть ограничения на сочетания кортежей, то результат эквивалентен операции INNER JOIN с таким же условием:

Таким образом, выражения t1, t2 WHERE p и t1 INNER JOIN t2 ON p синтаксически являются альтернативными формами записи одной и той же логической операции внутреннего соединения по предикату p. Синтаксис CROSS JOIN + WHERE для операции соединения называют устаревшим, его не рекомендует стандарт SQL ANSI [1] [2] .

Автор: Wagner Crivelini
Опубликовано: 09.07.2010

Версия текста: 1.1

Первое, что мы узнаем об SQL – это как писать выражения SELECT для выборки данных из таблицы. Такие выражения выглядят просто и очень похоже на обычный разговорный язык.

Но настоящие запросы зачастую гораздо сложнее, чем простые выражения SELECT.

Во-первых, нужные данные обычно разбиты на несколько разных таблиц. Это естественное следствие нормализации данных, которая является характерным свойством любой хорошо спланированной модели БД. SQL позволяет объединить эти данные.

В прошлом администраторы БД и разработчики помещали все нужные таблицы и/или представления в оператор FROM, а затем использовали оператор WHERE, чтобы определить, как должны комбинироваться записи из одной таблицы с записями из другой (чтобы сделать этот текст чуть-чуть более читаемым, я в дальнейшем буду писать просто «таблица», а не «таблица и/или представление»).

Однако, чтобы стандартизовать объединение данных, понадобилось довольно много времени. Это было сделано с помощью оператора JOIN (ANSI-SQL 92). К сожалению, некоторые детали использования оператора JOIN так и остаются неизвестными очень многим.

Прежде чем показать различный синтаксис JOIN, поддерживаемый T-SQL (в SQL Server 2008), я опишу несколько концепций, которые не следует забывать при любом соединении данных из двух или нескольких таблиц.

Начало: одна таблица, никакого JOIN

Если запрос обращается только к одному объекту, синтаксис будет очень простым, и никакое соединение не потребуется. Выражение будет старым добрым » SELECT fields FROM object » с другими необязательными операторами (то есть WHERE, GROUP BY, HAVING или ORDER BY).

Однако конечные пользователи не знают, что администраторы БД обычно прячут множество сложных соединений за одним красивым и простым в использовании представлением. Это делается по разным причинам, от безопасности данных до производительности БД. Например, администратор может дать конечному пользователю разрешение на доступ к одному представлению вместо нескольких рабочих таблиц, что, очевидно, повышает сохранность данных. А если говорить о производительности, можно создать представление, используя правильные параметры для соединения записей из разных таблиц, правильно использовать индексы и тем самым повысит производительность запроса.

Как бы то ни было, соединения в БД всегда есть, даже если конечный пользователь их и не видит.

Логика, стоящая за соединением таблиц

Много лет назад, когда я начинал работать с SQL, я узнал, что есть несколько типов соединения данных. Но мне потребовалось некоторое время, чтобы точно понять, что я делаю, соединяя таблицы. Возможно из-за того, что люди боятся математики, не часто можно услышать, что вся идея соединений таблиц – это теория множеств. Несмотря на заковыристое название, концепция так проста, что изучается в начальной школе.

Рисунок 1 очень похож на картинки из учебника для первого класса. Идея в том, чтобы найти в разных множествах соответствующие объекты. Это как раз то, чем занимается JOIN в SQL!

Рисунок 1. Комбинируем объекты из разных множеств.

Если вы поняли эту аналогию, все становится более осмысленным.

Представьте, что 2 множества на рисунке 1 – это таблицы, а цифры – это ключи, используемые для соединения таблиц. Таким образом, в каждом из множеств вместо целой записи мы видим только ключевые поля каждой таблицы. Результирующий набор комбинаций будет определяться типом используемого соединения, и это я как раз и собираюсь показать. Чтобы проиллюстрировать примеры, возьмем 2 таблицы, показанные ниже:

Таблица Table1

Таблица Table2

Скрипт для создания и заполнения таблиц приведен ниже:

Как можно заметить, этот скрипт не полностью обеспечивает ссылочную целостность. Я намеренно оставил таблицы без внешних ключей, чтобы лучше объяснить функциональность разных типов JOIN. Но я сделал это исключительно в целях обучения. Внешние ключи крайне полезны для обеспечения непротиворечивости данных, и их нельзя исключить ни из одной реальной БД.

Теперь мы готовы. Давайте рассмотрим типы JOIN, имеющиеся в T-SQL, их синтаксис и результаты, генерируемые ими.

INNER JOIN

Это наиболее часто используемое в SQL соединение. Оно возвращает пересечение двух множеств. В терминах таблиц, оно возвращает только записи из обеих таблиц, отвечающие указанному критерию.

На рисунке 2 показана диаграмма Венна, иллюстрирующая пересечение двух таблиц. Результат операции – закрашенная область.

Рисунок 2. INNER JOIN.

Теперь посмотрите на синтаксис объединения данных из таблиц Table1 и Table2 с использованием INNER JOIN.

Вот набор результатов, возвращаемый этим выражением:

Заметьте, что выдаются только данные из записей, имеющих одинаковые значения key2 в таблицах Table1 и Table2 .

Противоположностью INNER JOIN является OUTER JOIN. Существует три типа OUTER JOIN – полный, левый и правый. Рассмотрим каждый из них.

FULL JOIN

Полностью это соединение называется FULL OUTER JOIN (зарезервированное слово OUTER необязательно). FULL JOIN работает как объединение двух множеств. На рисунке 3 показана диаграмма Венна для FULL JOIN двух таблиц. Результатом операции опять же является закрашенная область.

Рисунок 3. FULL JOIN.

Синтаксис почти такой же, как показанный выше:

Набор результатов, возвращаемых этим выражением, выглядит так:

FULL JOIN возвращает все записи из таблиц Table1 и Table2 , без повторяющихся данных.

LEFT JOIN

Также известен как LEFT OUTER JOIN, и является частным случаем FULL JOIN. Дает все запрошенные данные из таблицы в левой части JOIN плюс данные из правой таблицы, пересекающиеся с первой таблицей. На рисунке 4 показана диаграмма Венна, иллюстрирующая LEFT JOIN для двух таблиц.

Рисунок 4. LEFT JOIN.

Результатом этого выражения будет:

Третья и четвертая записи ( key1 равен 6 и 7) содержат NULL-значения в последнем поле, потому что для них нет информации из второй таблицы. Это значит, что у нас есть значение в поле key2 в Table1 , но нет соответствующего ему значения в Table2 .

RIGHT JOIN

Также известен как RIGHT OUTER JOIN, и является еще одним частным случаем FULL JOIN. Он выдает все запрошенные данные из таблицы, стоящей в правой части оператора JOIN, плюс данные из левой таблицы, пересекающиеся с правой. Диаграмма Венна для RIGHT JOIN двух таблиц показана на рисунке 5.

Рисунок 5. RIGHT JOIN.

Как видите, синтаксис очень похож на показанный выше:

Результатом этого выражения будет:

Как видите, теперь записи с key1 , равным 6 и 7, отсутствуют в результатах, потому что для них нет соответствующих записей в правой таблице. Четыре записи содержат NULL в первом поле, поскольку для них нет данных в левой таблице.

CROSS JOIN

CROSS JOIN – это на самом деле Декартово произведение. При использовании CROSS JOIN генерируется точно тот же результат, что и при вызове двух таблиц (разделенных запятой) без всякого JOIN вообще. Это значит, что мы получим огромный набор результатов, где каждая запись из Table1 будет дублирована для каждой записи из Table2 . Если в Table1 содержится N1 записей, а в Table2 – N2 записей, в результате будет N1 х N2 записей.

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

Синтаксис CROSS JOIN таков:

Поскольку в Table1 содержится 5 записей, а в Table2 – еще 7, результат этого запроса будет содержать 35 записей (5 x 7).

Совершенно честно, я не могу сейчас припомнить ни одной реальной ситуации, когда мне понадобилось бы сгенерировать декартово произведение двух таблиц. Но если оно вам понадобится, есть CROSS JOIN.

Кроме всего прочего, стоит подумать и о производительности. Допустим, что вы случайно запустили на рабочем сервере запрос, содержащий CROSS JOIN для двух таблиц по миллиону записей в каждой. Это, несомненно, добавит вам головной боли. Возможно, у вашего сервера начнутся проблемы с производительностью, поскольку это запрос будет исполняться долго, и потреблять при этом существенное количество ресурсов сервера.

SELF JOIN

Оператор JOIN можно использовать для комбинирования любой пары таблиц, включая комбинацию таблицы с самой собой. Это и есть «SELF JOIN».

Посмотрите на классический пример, возвращающий имя начальника сотрудника (по таблице 1). В этом примере мы полагаем, что значение в field2 – фактически кодовый номер босса, следовательно, он связан с key1.

А вот результат запроса:

Последняя запись в данном примере показывает, что у Гарри нет начальника, другими словами, он №1 в иерархии компании.

Исключение пересечения множеств

Посмотрев на последнюю диаграмму Венна из приведенных выше, можно задаться простым вопросом: что, если мне нужны все записи из Table1, кроме тех, для которых есть соответствующие записи в Table2 . Что ж, это крайне полезно в повседневной работе, но для этого, очевидно, не нужен особый оператор JOIN.

Рисунок 6. Непересекающиеся записи в Таблице 1.

Посмотрите на предыдущие наборы результатов, и вы увидите, что нужно всего лишь добавить в SQL-запрос оператор WHERE, чтобы найти записи, содержащие NULL в ключе Table2 . Это даст нам набор результатов, соответствующий диаграмме Венна, показанной на рисунке 6.

Можно в этом запросе написать LEFT JOIN, например:

И, наконец, набор результатов будет выглядеть так:

При выполнении таких запросов нужно правильно выбирать поле для оператора WHERE. Нужно использовать поле, не допускающее NULL-значений. В противном случае набор результатов может содержать ненужные записи. Поэтому я и предложил использовать ключ второй таблицы, точнее, ее первичный ключ. Поскольку первичные ключи не могут содержать NULL-значения, это гарантирует, что набор результатов будет таким, как и предполагалось.

Слово о планах исполнения

По ходу действия мы подошли к важному моменту. Обычно мы не задумываемся об этом, но нужно знать, что планы исполнения SQL-запросов сперва вычисляют результат операторов FROM и JOIN (если таковой имеется), а только затем исполняют оператор WHERE.

Это верно как для SQL Server, так и для любой другой РСУБД.

Базовое понимание работы SQL важно для любого администратора БД или разработчика. Это помогает в работе. Если вам интересно, посмотрите на план выполнения запроса, приведенного выше (рисунок 7).

Рисунок 7. План исполнения запроса, использующего LEFT JOIN.

JOIN и индексы

Посмотрите еще раз на план исполнения запроса. Заметьте, он использует кластерные индексы для обеих таблиц. Использование индексов – лучший способ ускорить выполнение запросов. Но нужно обращать внимание на ряд деталей.

При создании запросов мы ожидаем, что SQL Server Query Optimizer будет использовать индексы таблиц для увеличения производительности. Мы также можем помочь Query Optimizer-у выбрать индексированные поля, являющиеся частью запроса.

Например, при использовании оператора JOIN, идеальный подход состоит в том, чтобы соединение основывалось на индексированных полях. Посмотрев в план исполнения, можно заметить, что используется кластерный индекс для Table2 . Этот индекс был автоматически создан по key2 при создании таблицы, поскольку key2 – это первичный ключ этой таблицы.

С другой стороны, таблица Table1 не индексирована по полю key2 . Из-за этого оптимизатор запросов пытается быть умным и увеличить производительность запроса к key2, используя единственный доступный индекс. Это табличный кластерный индекс, основанный на key1 , первичном ключе Table1 . Как видите, оптимизатор запросов – действительно умное средство. Но вы сильно поможете ему, если создадите новый (некластерный) индекс по key2 .

Если не забывать о ссылочной целостности, поле key2 должно быть внешним ключом Table1 , поскольку оно связано с другим полем другой таблицы (то есть Table2.key2 ).

Лично я считаю, что внешние ключи должны присутствовать во всех реальных моделях БД. Причем это хорошая идея – создавать некластерные индексы для всех внешних ключей. Вы всегда будете исполнять множество запросов, а также использовать оператор JOIN, основываясь на первичных и внешних ключах.

Важно: SQL Server автоматически создает кластерный индекс для первичных ключей. Однако по умолчанию он ничего не делает с внешними ключами. Проверьте, что ваша СУБД настроена надлежащим образом.

Неравенства

При создании SQL-запросов, использующих оператор JOIN, мы обычно сравниваем, равно ли одно поле одной таблицы другому полю другой таблицы. Но это не обязательный синтаксис. Можно использовать любой логический оператор, например, «не равно» (<>), «больше» (>), «меньше» ( Table1 , ту, у которой key1 равен 3. Проблема в том, что есть 6 записей и Table2, удовлетворяющая условиям соединения. Посмотрите на результат запроса:

Рекомендуем к прочтению

CROSS JOIN против INNER JOIN в SQL

CROSS JOIN = (ВНУТРЕННИЙ) JOIN = запятая («,»)

TL; DR Единственная разница между SQL CROSS JOIN, (INNER) JOIN и запятой («,») (кроме запятой, имеющей более низкий приоритет для порядка оценки) состоит в том, что (INNER) JOIN имеет ON, а CROSS JOIN и запятую — нет.


Повторные промежуточные продукты

Все три производят промежуточный концептуальный реляционный «декартовский» продукт в стиле SQL, то есть перекрестное соединение, всех возможных комбинаций строки из каждой таблицы. Это включено и / или ГДЕ, что уменьшает количество строк. SQL Fiddle

Стандарт SQL определяет <запятую> через продукт (7.5 1.b.ii), <перекрестное соединение> через <запятую> (7.7 1.a) и JOIN ON <условие поиска> через <запятую> плюс WHERE (7.7 1.b ).

Как говорит Википедия:

Перекрестное соединение

CROSS JOIN возвращает декартово произведение строк из таблиц в соединении. Другими словами, он будет производить строки, которые объединяют каждую строку из первой таблицы с каждой строкой из второй таблицы.

Внутреннее соединение

[…] Результат объединения может быть определен как результат первого взятия декартова произведения (или перекрестного объединения) всех записей в таблицах (объединение каждой записи в таблице A с каждой записью в таблице B) и затем возврата все записи, которые удовлетворяют предикату соединения.

В «неявной нотации объединения» просто перечисляются таблицы для объединения в предложении FROM оператора SELECT с использованием запятых для их разделения. Таким образом, он определяет перекрестное соединение

Re OUTER JOINs и использование ON против ГДЕ в них см. Условия в LEFT JOIN (ВНЕШНЕЕ СОЕДИНЕНИЕ) против INNER JOIN .

Зачем сравнивать столбцы между таблицами?

Когда нет повторяющихся строк:

Каждая таблица содержит строки, которые составляют истинный оператор из определенного шаблона оператора заполнения-заполненных-именованных-бланков. (Это делает истинное предложение из — удовлетворяет — определенный (характерный) предикат .)

  • Базовая таблица содержит строки, которые делают истинный оператор из некоторого заданного DBA шаблона оператора:

    /* rows where
    customer C.CustomerID has age C.Age and ...
    */
    FROM Customers C
  • Промежуточный продукт объединения содержит строки, которые делают истинное утверждение из AND шаблонов его операндов:

    /* rows where
        customer C.CustomerID has age C.Age and ...
    AND movie M.Movie is rented by customer M.CustomerID and ...
    */
    FROM Customers C CROSS JOIN Movies M
  • ON & WHERE условия AND, чтобы дать дополнительный шаблон. Значение снова строки, которые удовлетворяют этому шаблону:

    /* rows where
        customer C.CustomerID has age C.Age and ...
    AND movie M.Movie is rented by customer M.CustomerID and ...
    AND C.CustomerID = M.CustomerID
    AND C.Age >= M.[Minimum Age]
    AND C.Age = 18
    */
    FROM Customers C INNER JOIN Movies M
    ON C.CustomerID = M.CustomerID
    AND C.Age >= M.[Minimum Age]
    WHERE C.Age = 18

В частности, сравнение столбцов для (SQL) равенства между таблицами означает, что строки, хранящиеся в продукте из частей шаблона объединенных таблиц, имеют одинаковое (не NULL) значение для этих столбцов. Это просто совпадение, что многие строки обычно удаляются путем сравнения на равенство между таблицами — что необходимо и достаточно для характеристики нужных вам строк.

Просто напишите SQL для шаблона для строк, которые вы хотите!

Значение запросов (и таблиц и условий) см. В разделе:
Как получить совпадающие данные из другой таблицы SQL для двух разных столбцов: Inner Join и / или Union?
Есть ли эмпирическое правило для построения SQL-запроса из понятного человеку описания?

Перегрузка «перекрестное соединение»

К сожалению, термин «перекрестное соединение» используется для:

  • Промежуточный продукт.
  • CROSS JOIN
  • (ВНУТРЕННИЙ) СОЕДИНИТЕ с ON или WHERE, который не сравнивает столбцы из одной таблицы с столбцами из другой. (Так как это имеет тенденцию возвращать так много промежуточных строк продукта.)

Эти различные значения смешиваются. (Например, как в других ответах и ​​комментариях здесь.)

Использование CROSS JOIN против (INNER) JOIN против запятой

Общее соглашение:

  • Используйте CROSS JOIN тогда и только тогда, когда вы не сравниваете столбцы между таблицами. Это означает, что отсутствие сравнений было преднамеренным.
  • Используйте (INNER) JOIN с ON тогда и только тогда, когда вы сравниваете столбцы между таблицами. (Плюс, возможно, другие условия.)
  • Не используйте запятую.

Как правило, условия не для пар таблиц сохраняются для WHERE. Но их, возможно, придется поместить в (n INNER) JOIN ON, чтобы получить соответствующие строки для аргумента RIGHT, LEFT или FULL (OUTER) JOIN.

Re «Не используйте запятую» Смешивание запятой с явным JOIN может ввести в заблуждение, потому что запятая имеет меньший приоритет. Но учитывая роль промежуточного продукта в значении CROSS JOIN, (INNER) JOIN и запятой, аргументы для соглашения выше о том, что он вообще не используется, шатки. Перекрестное соединение или запятая — это как (ВНУТРЕННЕЕ) соединение, находящееся в состоянии ИСТИНА. Промежуточный продукт, ON и WHERE, все вводят AND в соответствующем предикате. Тем не менее, можно думать о INNER JOIN ON — скажем, о создании выходной строки только при поиске пары входных строк, удовлетворяющих условию ON — тем не менее он возвращает строки перекрестного соединения, которые удовлетворяют условию. Единственная причина, по которой ON должен был дополнить запятую в SQL, это написать OUTERСоединения. Конечно, выражение должно прояснить его значение; но то, что ясно, зависит от того, что вещи означают.

Диаграммы Венна Диаграмма Венна с двумя пересекающимися кругами может иллюстрировать разницу между выходными строками для INNER, LEFT, RIGHT & FULL JOIN для одного и того же входа. И когда ВКЛЮЧЕНО, безусловно, ИСТИНА, результат ВНУТРЕННЕГО СОЕДИНЕНИЯ такой же, как ВРЕМЕННОЕ СОЕДИНЕНИЕ. Также он может иллюстрировать строки ввода и вывода для INTERSECT, UNION и EXCEPT. И когда оба входа имеют одинаковые столбцы, результат INTERSECT такой же, как для стандартного SQL NATURAL JOIN, а результат EXCEPT такой же, как для некоторых идиом, включающих LEFT & RIGHT JOIN. Но это не иллюстрирует, как (INNER) JOIN работает в целом. На первый взгляд это кажется правдоподобным . Он может определить детали ввода и / или вывода дляособые случаиON, PK (первичные ключи), FK (внешние ключи) и / или SELECT. Все, что вам нужно сделать, чтобы увидеть это, это определить, какие именно элементы наборов представлены кружками . (Какие запутанные представления никогда не проясняются.) (Помните, что обычно для выходных строк объединений заголовки отличаются от входных строк . А таблицы SQL — это пакеты, а не наборы строк с NULL .)

Как присоединить три таблицы в SQL запросе

Объединение трех таблиц в одном запросе SQL может быть очень сложно, если вы не очень хорошо понимаете объединение в SQL. Объединения SQL всегда были сложным не только для новых программистов, но и для профессионалов, которые уже долго занимаются программированием и используют SQL более чем 2 -х до 3 -х лет. Есть достаточно причин, чтобы запутаться в SQL JOIN, начиная от различных типов SQL JOIN like INNER и OUTER join, LEFT и RIGHT outer join, CROSS join и т.д. Между всеми этими основами, наиболее важным является регистрация, объединения нескольких таблиц. Если вам нужны данные из нескольких таблиц в одном запросе SELECT, вам нужно использовать либо подзапрос либо JOIN. Большую часть времени мы только соединяем две таблицы, как Employee и Department, но иногда вам может потребоваться присоединение более двух таблиц и наиболее частый случай – объединения трех таблиц в SQL.

В случае присоединения трех таблиц, первая относится к таблице 2, а затем таблица 2 относится к таблице 3. Если вы посмотрите внимательно, то вы обнаружите , что таблица 2 представляет собой присоединенную таблицу, которая содержит первичный ключ из обеих таблиц 1 и 2. Как мы сказали, это может быть очень запутанным, чтобы понять объединение трех или более таблиц.

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

SQL Join также является очень популярной темой в SQL и там всегда были некоторые вопросы из соединений, как разница между INNER и OUTER JOIN, например SQL – запрос с JOIN Employee Department и разница между LEFT и RIGHT OUTER JOIN и т.д. Короче говоря это одна из самых важных тем в SQL как из опыта так  и из точки зрения цели.

Единственный способ освоить SQL JOIN, это сделать как можно больше упражнений, насколько это возможно. Если бы вы могли решить большинство головоломок SQL из классической книги Джо Селко, SQL Puzzles and Answers, 2nd edition, вы были бы более уверены в работе с SQL JOIN, хоть это быть две, три или четыре таблицы.

 

Объединение трех таблиц, синтаксис в SQL

Вот общий синтаксис запроса SQL, чтобы присоединить три или более таблиц. Этот SQL-запрос должен работать во всех основных баз данных, например в базе данных MySQL, Oracle, Microsoft SQLServer, Sybase и PostgreSQL:

SELECT t1.col, t3.col 
FROM table1 join table2 ON table1.primarykey = table2.foreignkey
join table3 ON table2.primarykey = table3.foreignkey

 

Мы сначала присоединим таблице 2 к таблице 1, которые создадут временную таблицу с комбинированными данными из table1 и table2, а затем присоединим к Table3. Эта формула может быть распространена на более чем 3 -х таблиц в N таблиц, Вам просто нужно убедиться, что SQL – запрос должен иметь N-1 join, чтобы присоединить N таблиц. Как для объединения двух таблиц мы требуем 1 join а для присоединения 3 таблиц нам нужно 2 join.

Вот хорошая схема, которая хорошо показывает, как применять различные типы присоединений, например как работают в SQL inner, left outer, right outer и cross joins:

 

SQL запрос по присоединению трех таблиц в MySQL

Для того, чтобы лучше понять присоединение 3 таблицы в SQL запросе, давайте рассмотрим пример. Рассмотрим популярный пример Employee и Department. В нашем случае мы использовали таблицу ссылок под названием Register, который связывает или имеет отношение Employee для Department. Первичный ключ таблицы Employee (emp_id) является внешним ключом в Register и аналогичным образом, первичный ключ таблицы Department (dept_id) является внешним ключом в таблице Register.

Для того , чтобы написать запрос SQL для печати имя сотрудника и название отдела мы должны присоединиться к трем таблицам. Первое присоединение Employee и Register и создают временную таблицу, с колонкой dept_id. Теперь второе присоединение таблицы Department к этой временной таблицы по колонке dept_id, чтобы получить желаемый результат. Вот полный SELECT, пример SQL – запроса, чтобы присоединиться к 3 таблицам, и она может быть расширена, чтобы присоединиться к более чем 3 или N таблицам.

mysql> SELECT * FROM Employee;
+--------+----------+--------+
| emp_id | emp_name | salary |
+--------+----------+--------+
| 1      | Антон    |   1900 |
| 2      | Макс     |   3800 |
| 3      | Артем    |   5500 |
| 4      | Дмитрий  |   7600 |
+--------+----------+--------+
4 rows IN SET (0.00 sec)

mysql> SELECT * FROM Department;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 101     | Sales     |
| 102     | Marketing |
| 103     | Finance   |
+---------+-----------+
3 rows IN SET (0.00 sec)

mysql> SELECT * FROM Register;
+--------+---------+
| emp_id | dept_id |
+--------+---------+
|      1 |     101 |
|      2 |     102 |
|      3 |     103 |
|      4 |     102 |
+--------+---------+
4 rows IN SET (0.00 sec)

mysql> SELECT emp_name, dept_name FROM Employee e 
JOIN Register r ON e.emp_id=r.emp_id 
JOIN Department d ON r.dept_id=d.dept_id;
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| Антон    | Sales     |
| Макс     | Marketing |
| Артем    | Finance   |
| Дмитрий  | Marketing |
+----------+-----------+
4 rows IN SET (0.01 sec)

 

Если вы хотите понять это лучше, попытайтесь объединить таблицы шаг за шагом. Таким образом, вместо того, чтобы присоединиться 3 таблицы за один раз, сначала соединить 2 таблицы и посмотреть, как будет выглядеть таблица результатов. Это все о том, как присоединить три таблицы в одном запросе SQL в реляционной базе данных. Кстати, в этом примере SQL JOIN, мы использовали ANSI SQL, и он будет работать в другой реляционной базы данных, а также, Oracle, SQL Server, Sybase, PostgreSQL и т.д. Дайте нам знать, если вы сталкивались с какой – либо проблемой во время объединения 3 таблицы запросом JOIN в любой другой базе данных.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Полное соединение · Loginom Help

ИмяId города
Андрей1
Леонид2
Сергей1
Григорий4

IdГород
1Москва
2Санкт-Петербург
3Казань

ИмяId городаГород
Андрей1Москва
Андрей1Санкт-Петербург
Андрей1Казань
Леонид2Москва
Леонид2Санкт-Петербург
Леонид2Казань
Сергей1Москва
Сергей1Санкт-Петербург
Сергей1Казань
Григорий4Москва
Григорий4Санкт-Петербург
Григорий4Казань

ИмяId города
Андрей1
Леонид2
Сергей1
Григорий4

IdГород
1Москва
2Санкт-Петербург
3Казань

ИмяId городаГород
Андрей1Москва
Леонид2Санкт-Петербург
Сергей1Москва
Григорий4<null>
<null>Казань

ИмяId городаГородId
Андрей1Москва1
Леонид2Санкт-Петербург2
Сергей1Москва1
Григорий4<null>
<null>Казань3


SELECT employees.employee_id,

       employees.last_name,

       positions.title

FROM employees

INNER JOIN positions

   ON employees.position_id = positions.position_id;

employee_idlast_namefirst_nameposition_id
10000PetrovAlex1
10001IvanovMax2
10002SidorovPiter3
10003NikonovSimon

position_idtitle
1Manager
2Project Planner
3Programmer
4Data Analyst


SELECT employees.employee_id,

       employees.last_name,

       positions.title

  FROM employees

INNER JOIN positions

    ON employees.position_id = positions.position_id;

employee_idlast_nametitle
10000PetrovManager
10001IvanovProject Planner
10002SidorovProgrammer


SELECT employees.employee_id,

       employees.last_name,

       positions.title

  FROM employees, positions

WHERE employees.position_id = positions.position_id;


SELECT employees.employee_id,

       employees.last_name,

       positions.title

  FROM employees

  LEFT OUTER JOIN positions

    ON employees.position_id = positions.position_id;

employee_idlast_namefirst_nameposition_id
10000PetrovAlex1
10001IvanovMax2
10002SidorovPiter3
10003NikonovSimon

position_idtitle
1Manager
2Project Planner
3Programmer
4Data Analyst


SELECT employees.employee_id,

       employees.last_name,

       positions.title

  FROM employees

  LEFT OUTER JOIN positions

    ON employees.position_id = positions.position_id;

employee_idlast_nametitle
10000PetrovManager
10001IvanovProject Planner
10002SidorovProgrammer
10003Nikonov


SELECT *

  FROM positions

CROSS JOIN departments;

position_idtitle
1Manager
2Project Planner
3Programmer
4Data Analyst

department_iddepartment_name
30HR
999Sales


SELECT *

  FROM positions

CROSS JOIN departments;

position_idtitledepartment_iddepartment_name
1Manager30HR
1Manager999Sales
2Project Manager30HR
2Project Manager999Sales
3Programmer30HR
3Programmer999Sales
4Data Analyst30HR
4Data Analyst999Sales

SELECT ColumnName_1,

ColumnName_2,

ColumnName_N

FROM [Table_1]

CROSS JOIN [Table_2]

SELECT ColumnName_1,

ColumnName_2,

ColumnName_N

FROM [Table_1], [Table_2]

CREATE TABLE Meals (MealName VARCHAR (100))

CREATE TABLE Drinks (DrinkName VARCHAR (100))

INSERT INTO Drinks

VALUES (‘Апельсиновый сок’), (‘Чай’), (‘Cofee’)

INSERT INTO Meals

VALUES (‘Омлет’), (‘Жареное яйцо’), (‘Колбаса’)

ВЫБЕРИТЕ *

FROM Meals;

ВЫБРАТЬ *

ИЗ Напитков

ВЫБРАТЬ * ИЗ ПИТАНИЯ

CROSS JOIN Напитки

ВЫБРАТЬ * ИЗ ЕДА

, Напитки

SELECT CONCAT_WS (‘-‘, MealName, DrinkName) AS MenuList

FROM Meals CROSS JOIN

Напитки

SELECT * FROM Meals

CROSS JOIN Напитки

OPTION (MERGE JOIN)

GO

SELECT * FROM Meals

CROSS JOIN Drinks

43 OPTION (

43 OPTION)



Идентификатор клиента CustomerName ContactName Адрес Город Почтовый индекс Страна
1 Альфредс Футтеркисте Мария Андерс Obere Str. 57 Берлин 12209 Германия
2 Ana Trujillo Emparedados y helados Ана Трухильо Avda.de la Constitución 2222 México D.F. 05021 Мексика
3 Антонио Морено Такерия Антонио Морено Матадерос 2312 México D.F. 05023 Мексика

Код заказа CustomerID EmployeeID Дата заказа ShipperID
10308 2 7 1996-09-18 3
10309 37 3 1996-09-19 1
10310 77 8 1996-09-20 2