Виды join

Оператор JOIN используется для соединения двух или нескольких таблиц. Соединение таблиц может быть внутренним (INNER) или внешним (OUTER), причем внешнее соединение может быть левым (LEFT), правым (RIGHT) или полным (FULL). Далее на примере двух таблиц рассмотрим различные варианты их соединения.

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

FROM <таблица 1>  [INNER]  {{LEFT | RIGHT | FULL } [OUTER]} JOIN <таблица 2> [ON <предикат>]

Предикат в этой конструкции определяет условие соединения строк из разных таблиц.

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

id name id sum -- ---- -- ---- 1 bmw 1 250 2 opel 5 450 3 kia 3 300 4 audi 6 400

Далее соединим эти таблицы по полю id несколькими различными способами. Совпадающие значения выделены красным для лучшего восприятия.

1. Внутреннее соединение (INNER JOIN) означает, что в результирующий набор попадут только те соединения строк двух таблиц, для которых значение предиката равно TRUE. Обычно используется для объединения записей, которые есть и в первой и во второй таблице, т. е. получения пересечения таблиц:

Виды join

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

Итак, сам запрос:

SELECT * FROM 'Auto' INNER JOIN 'Selling' ON 'Auto'.id = 'Selling'.id

И результат:

id name id sum -- ---- -- ---- 1 bmw 1 250 3 kia 3 300

Ключевое слово INNER в запросе можно опустить.

В итоге запрос отбирает и соединяет те записи, у которых значение поля id в обоих таблицах совпадает.

2. Внешнее соединение (OUTER JOIN) бывает нескольких видов. Первым рассмотрим полное внешнее объединение (FULL OUTER JOIN), которое объединяет записи из обоих таблиц (если условие объединения равно true) и дополняет их всеми записями из обоих таблиц, которые не имеют совпадений. Для записей, которые не имеют совпадений из другой таблицы, недостающее поле будет иметь значение NULL. Граф выборки записей будет иметь вид:

Виды join

Переходим к запросу:

SELECT * FROM 'Auto' FULL OUTER JOIN 'Selling' ON 'Auto'.id = 'Selling'.id

Результат:

id name id sum -- ---- -- ---- 1 bmw 1 250 2 opel NULL NULL 3 kia 3 300 4 audi NULL NULL NULL NULL 5 450 NULL NULL 6 400

То есть мы получили все записи, которые есть в обоих таблицах. Записи у которых значение поля id совпадает соединяются, а у записей для которых совпадений не найдено недостающие поля заполняются значением NULL.

Ключевое слово OUTER можно опустить.

3. Левое внешнее объединение (LEFT OUTER JOIN). В этом случае получаем все записи удовлетворяющие условию объединения, плюс все оставшиеся записи из внешней таблицы, которые не удовлетворяют условию объединения. Граф выборки:

Виды join

Запрос:

SELECT * FROM 'Auto' LEFT OUTER JOIN 'Selling' ON 'Auto'.id = 'Selling'.id

Результат:

id name id sum -- ---- -- ---- 1 bmw 1 250 2 opel NULL NULL 3 kia 3 300 4 audi NULL NULL

Запрос также можно писать без ключевого слова OUTER.

В итоге здесь мы получили все записи таблицы Auto. Записи для которых были найдены совпадения по полю id в таблице Selling соединяются, для остальных недостающие поля заполняются значением NULL.

Еще существует правое внешнее объединение (RIGHT OUTER JOIN). Оно работает точно также как и левое объединение, только  в качестве внешней таблицы будет использоваться правая (в нашем случае таблица Selling или таблица Б на графе).

Далее рассмотрим остальные возможные выборки с использованием объединения двух таблиц.

4. Получить все записи из таблицы А, которые не имеют объединения из таблицы Б. Граф:

Виды join

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

Запрос:

SELECT * FROM 'Auto' LEFT OUTER JOIN 'Selling' ON 'Auto'.id = 'Selling'.id WHERE 'Selling'.id IS null

Результат:

id name id sum -- ---- -- ---- 2 opel NULL NULL 4 audi NULL NULL

5. И последний вариант, получить все записи из таблицы А и Таблицы Б, которые не имеют объединений. Граф:

Виды join

В нашем случае мы должны получить все записи из таблицы Auto, которые не связаны с таблицей Selling, и все записи из таблицы Selling, которые не имеют сопоставления из таблицы Auto.

Запрос:

SELECT * FROM 'Auto' FULL OUTER JOIN 'Selling' ON 'Auto'.id = 'Selling'.id WHERE 'Auto'.id IS null OR 'Selling'.id IS null

Результат:

id name id sum -- ---- -- ---- 2 opel NULL NULL 4 audi NULL NULL NULL NULL 5 450 NULL NULL 6 400

На этом все, до новых встреч на страницах блога.

webcodius.ru

Ключевое слово join в SQL используется при построении select выражений. Инструкция Join позволяет объединить колонки из нескольких таблиц в одну. Объединение происходит временное и целостность таблиц не нарушается. Существует три типа join-выражений:

  • inner join;
  • outer join;
  • cross join;

В свою очередь, outer join может быть left, right и full (слово outer обычно опускается).

В качестве примера (DBMS Oracle) создадим две простые таблицы и сконструируем для них SQL-выражения с использованием join.

В первой таблице будет хранится ID пользователя и его nick-name, а во второй — ID ресурса, имя ресурса и ID пользователя, который может этот ресурс администрировать.

  create table t_users (  t_id number(11, 0),  t_nick varchar(16),  primary key (t_id) )    create table t_resources (  t_id number(11, 0),  t_name varchar(16),  t_userid number (11, 0),  primary key (t_id) )  

Содержимое таблиц пусть будет таким:

  T_ID T_NICK   1 user1    3 user3   4 user4     T_ID T_NAME T_USERID    1 res1 3    2 res2 1    3 res3 2    5 res5 3   

Конструкция join выглядит так:

  ... join_type join table_name on condition ...  

Где join_type — тип join-выражения, table_name — имя таблицы, которая присоединяется к результату, condition — условие объединения таблиц.

Кострукция join располагается сразу после select-выражения. Можно использовать несколько таких конструкций подряд для объединения соответствующего кол-ва таблиц. Логичнее всего использовать join в том случае, когда таблица имеет внешний ключ (foreign key).

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

  select t_resources.t_name, t_users.t_nick   from t_resources    inner join t_users on t_users.t_id = t_resources.t_userid  

Результат будет таким:

   T_NAME T_NICK    res2 user1    res1 user3    res5 user3   

В случае с left join из главной таблицы будут выбраны все записи, даже если в присоединяемой таблице нет совпадений, то есть условие condition не учитывает присоединяемую (правую) таблицу. Пример:

  select t_resources.t_name, t_users.t_nick   from t_resources    left join t_users on t_users.t_id = t_resources.t_userid  

Результат выполнения запроса:

   T_NAME T_NICK    res1 user3    res2 user1    res3 (null)    res5 user3   

Результат показывает все ресурсы и их администраторов, вне зависимотсти от того есть они или нет.

Right join отображает все строки удовлетворяющие правой части условия condition, даже если они не имеют соответствия в главной (левой) таблице:

  select t_resources.t_name, t_users.t_nick   from t_resources    right join t_users on t_users.t_id = t_resources.t_userid  

А результат будет следующим:

   T_NAME T_NICK    res2 user1    res1 user3    res5 user3    (null) user4   

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

Full outer join (ключевое слово outer можно опустить) необходим для отображения всех возможных комбинаций строк из нескольких таблиц. Иными словами, это объединение результатов left и right join.

  select t_resources.t_name, t_users.t_nick   from t_resources    full join t_users on t_users.t_id = t_resources.t_userid  

А результат будет таким:

   T_NAME T_NICK    res1 user3    res2 user1    res3 (null)    res5 user3    (null) user4   

Некоторые СУБД не поддерживают такую функциональность (например, MySQL), в таких случаях обычно используют объединение двух запросов:

  select t_resources.t_name, t_users.t_nick   from t_resources   left join t_users on t_users.t_id = t_resources.t_userid  union  select t_resources.t_name, t_users.t_nick   from t_resources   right join t_users on t_users.t_id = t_resources.t_userid  

Наконец, cross join. Этот тип join еще называют декартовым произведением (на английском — cartesian product). Настоятельно рекомендую использовать его с умом, так как время выполнения запроса с увеличением числа таблиц и строк в них растет нелинейно. Вот пример запроса, который аналогичен cross join:

  select t_resources.t_name, t_users.t_nick    from t_resources, t_users  

Конструкция Join (в сочетании с другими SQL конструкциями, например, group by) часто встречается при программировании под базы данных. Думаю, эта статья будет вам полезна.

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

www.javenue.info

Две синтаксические формы реализации соединений

Для соединения таблиц можно использовать две разные синтаксические формы оператора соединения:

  • явный синтаксис соединения (синтаксис соединения ANSI SQL:1992);

  • неявный синтаксис соединения (синтаксис соединения «старого стиля»).

Синтаксис соединения ANSI SQL:1992 был введен стандартом SQL92 и определяет операции соединения явно, т.е. используя соответствующее имя для каждого типа операции соединения. При явном объявлении соединения используются следующие ключевые слова:

  • CROSS JOIN;

  • [INNER] JOIN;

  • LEFT [OUTER] JOIN;

  • RIGHT [OUTER] JOIN;

  • FULL [OUTER] JOIN.

Ключевое слово CROSS JOIN определяет декартово произведение двух таблиц. Ключевое слово INNER JOIN определяет естественное соединение двух таблиц, а LEFT OUTER JOIN и RIGHT OUTER JOIN определяют одноименные операции соединения. Наконец, ключевое слово FULL OUTER JOIN определяет соединение правого и левого внешнего соединений. Все эти операции соединения рассматриваются в последующих разделах.

Неявный синтаксис оператора соединения является синтаксисом «старого стиля», где каждая операция соединения определяется неявно посредством предложения WHERE, используя так называемые столбцы соединения.

Для операций соединения рекомендуется использовать явный синтаксис, т.к. это повышает надежность запросов. По этой причине во всех примерах далее, связанных с операциями соединения, используются формы явного синтаксиса. Но в нескольких первых примерах также будет продемонстрирован и синтаксис «старого стиля».

Естественное соединение

Термины «естественное соединение» (natural join) и «соединение по эквивалентности» (equi-join) часто используют синонимично, но между ними есть небольшое различие. Операция соединения по эквивалентности всегда имеет одну или несколько пар столбцов с идентичными значениями в каждой строке. Операция, которая устраняет такие столбцы из результатов операции соединения по эквивалентности, называется естественным соединением. Наилучшим способом объяснить естественное соединение можно посредством примера:

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

В этом примере в инструкции SELECT для выборки указаны все столбцы таблиц для сотрудника Employee и отдела Department. Предложение FROM инструкции SELECT определяет соединяемые таблицы, а также явно указывает тип операции соединения — INNER JOIN. Предложение ON является частью предложения FROM и указывает соединяемые столбцы в обеих таблицах. Выражение «Employee.DepartamentNumber = Department.Number» определяет условие соединения, а оба столбца условия называются столбцами соединения.

Результат выполнения этого запроса:

Эквивалентный запрос с применением неявного синтаксиса («старого стиля») будет выглядеть следующим образом:

Эта форма синтаксиса имеет два значительных различия с явной формой: список соединяемых таблиц указывается в предложении FROM, а соответствующее условие соединения указывается в предложении WHERE посредством соединяемых столбцов.

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

На предыдущих примерах можно проиллюстрировать принцип работы операции соединения. Но при этом следует иметь в виду, что это всего лишь представление о процессе соединения, т.к. в действительности компонент Database Engine выбирает реализацию операции соединения из нескольких возможных стратегий. Представьте себе, что каждая строка таблицы Employee соединена с каждой строкой таблицы Department. В результате получится таблица с семью столбцами (4 столбца из таблицы Employee и 3 из таблицы Department) и 21 строкой.

Далее, из этой таблицы удаляются все строки, которые не удовлетворяют условию соединения «Employee.Number = Department.Number». Оставшиеся строки представляют результат первого примера выше. Соединяемые столбцы должны иметь идентичную семантику, т.е. оба столбца должны иметь одинаковое логическое значение. Соединяемые столбцы не обязательно должны иметь одинаковое имя (или даже одинаковый тип данных), хотя часто так и бывает.

Система базы данных не может определить логическое значение столбца. Например, она не может определить, что между столбцами номера проекта и табельного номера сотрудника нет ничего общего, хотя оба они имеют целочисленный тип данных. Поэтому система базы данных может только проверить тип данных и длину строк. Компонент Database Engine требует, что соединяемые столбцы имели совместимые типы данных, например INT и SMALLINT.

База данных SampleDb содержит три пары столбцов, где каждый столбец в паре имеет одинаковое логическое значение (а также одинаковые имена). Таблицы Employee и Department можно соединить по столбцам Employee.DepartmentNumber и Department.Number. Столбцами соединения таблиц Employee и Works_on являются столбцы Employee.Id и Works_on.EmpId. Наконец, таблицы Project и Works_on можно соединить по столбцам Project.Number и Works_on.ProjectNumber.

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

В большинстве инструкций SELECT столбцы не требуют уточнения, хотя обычно рекомендуется применять уточнение столбцов с целью улучшения понимания кода. Если же имена столбцов в инструкции SELECT неоднозначны (как, например, столбцы Number в таблицах Project и Department) использование уточненных имен столбцов является обязательным.

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

Использование уточненного имени столбца Project.Number в примере выше не является обязательным, поскольку в данном случае нет никакой двусмысленности в отношении их имен. В дальнейшем во всех примерах будет использоваться только явный синтаксис соединения.

В примере ниже показано еще одно применение внутреннего соединения:

Соединение более чем двух таблиц

Теоретически количество таблиц, которые можно соединить в инструкции SELECT, неограниченно. (Но одно условие соединения совмещает только две таблицы!) Однако для компонента Database Engine количество соединяемых таблиц в инструкции SELECT ограничено 64 таблицами.

В примере ниже показано соединение трех таблиц базы данных SampleDb:

В этом примере происходит выборка имен и фамилий всех аналитиков (Job = ‘Аналитик’), чей отдел находится в Санкт-Петербурге (Location = ‘Санкт-Петербург’). Результат запроса, приведенного в примере выше, можно получить только в том случае, если соединить, по крайней мере, три таблицы: Works_on, Employee и Department. Эти таблицы можно соединить, используя две пары столбцов соединения:

Обратите внимание, что для осуществления естественного соединения трех таблиц используется два условия соединения, каждое из которых соединяет по две таблицы. А при соединении четырех таблиц таких условий соединения требуется три. В общем, чтобы избежать получения декартового продукта при соединении n таблиц, требуется применять n — 1 условий соединения. Конечно же, допустимо использование более чем n — 1 условий соединения, а также других условий, для того чтобы еще больше уменьшить количество элементов в результирующем наборе данных.

Декартово произведение

В предшествующем разделе мы рассмотрели возможный способ создания естественного соединения. На первом шаге этого процесса каждая строка таблицы Employee соединяется с каждой строкой таблицы Department. Эта операция называется декартовым произведением (cartesian product). Запрос для создания соединения таблиц Employee и Department, используя декартово произведение, показан в примере ниже:

Декартово произведение соединяет каждую строку первой таблицы с каждой строкой второй. В общем, результатом декартового произведения первой таблицы с n строками и второй таблицы с m строками будет таблица с n*m строками. Таким образом, результирующий набор запроса в примере выше имеет 7 х 3 = 21 строку (эти строки содержат дублированные значения).

На практике декартово произведение применяется крайне редко. Иногда пользователи получают декартово произведение двух таблиц, когда они забывают включить условие соединения в предложении WHERE при использовании неявного синтаксиса соединения «старого стиля». В таком случае полученный результат не соответствует ожидаемому, т.к. содержит лишние строки. Наличие неожидаемо большого количества строк в результате служит признаком того, что вместо требуемого естественного соединения двух таблиц было получено декартово произведение.

Внешнее соединение

В предшествующих примерах естественного соединения, результирующий набор содержал только те строки с одной таблицы, для которых имелись соответствующие строки в другой таблице. Но иногда кроме совпадающих строк бывает необходимым извлечь из одной или обеих таблиц строки без совпадений. Такая операция называется внешним соединением (outer join).

В примере ниже показана выборка всей информации для сотрудников, которые проживают и работают в одном и том же городе. Здесь используется таблица EmployeeEnh, которую мы создали в статье «Инструкция SELECT: расширенные возможности» при обсуждении оператора UNION.

Результат выполнения этого запроса:

В этом примере получение требуемых строк осуществляется посредством естественного соединения. Если бы в этот результат потребовалось включить сотрудников, проживающих в других местах, то нужно было применить левое внешнее соединение. Данное внешнее соединение называется левым потому, что оно возвращает все строки из таблицы с левой стороны оператора сравнения, независимо от того, имеются ли совпадающие строки в таблице с правой стороны. Иными словами, данное внешнее соединение возвратит строку с левой таблицы, даже если для нее нет совпадения в правой таблице, со значением NULL соответствующего столбца для всех строк с несовпадающим значением столбца другой, правой, таблицы. Для выполнения операции левого внешнего соединения компонент Database Engine использует оператор LEFT OUTER JOIN.

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

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

Как можно видеть в результате выполнения запроса, когда для строки из левой таблицы (в данном случае EmployeeEnh) нет совпадающей строки в правой таблице (в данном случае Department), операция левого внешнего соединения все равно возвращает эту строку, заполняя значением NULL все ячейки соответствующего столбца для несовпадающего значения столбца правой таблицы. Применение правого внешнего соединения показано в примере ниже:

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

Кроме левого и правого внешнего соединения, также существует полное внешнее соединение, которое является объединением левого и правого внешних соединений. Иными словами, результирующий набор такого соединения состоит из всех строк обеих таблиц. Если для строки одной из таблиц нет соответствующей строки в другой таблице, всем ячейкам строки второй таблицы присваивается значение NULL. Для выполнения операции полного внешнего соединения используется оператор FULL OUTER JOIN.

Любую операцию внешнего соединения можно эмулировать, используя оператор UNION совместно с функцией NOT EXISTS. Таким образом, запрос, показанный в примере ниже, эквивалентен запросу левого внешнего соединения, показанному ранее. В данном запросе осуществляется выборка сотрудников (с включением полной информации) для таких городов, в которых сотрудники или только проживают или проживают и работают:

Первая инструкция SELECT объединения определяет естественное соединение таблиц EmployeeEnh и Department по столбцам соединения City и Location. Эта инструкция возвращает все города для всех сотрудников, в которых сотрудники и проживают и работают. Дополнительно, вторая инструкция SELECT объединения возвращает все строки таблицы EmployeeEnh, которые не отвечают условию в естественном соединении.

Другие формы операций соединения

В предшествующих разделах мы рассмотрели наиболее важные формы соединения. Но существуют и другие формы этой операции, которые мы рассмотрим в следующих подразделах.

Тета-соединение

Условие сравнения столбцов соединения не обязательно должно быть равенством, но может быть любым другим сравнением. Соединение, в котором используется общее условие сравнения столбцов соединения, называется тета-соединением. В примере ниже показана операция тета-соединения, в которой используется условие «меньше чем». Данный запрос возвращает все комбинации информации о сотрудниках и отделах для тех случаев, когда место проживания сотрудника по алфавиту идет перед месторасположением любого отдела, в котором работает этот служащий:

Результат выполнения этого запроса:

В этом примере сравниваются соответствующие значения столбцов City и Location. В каждой строке результата значение столбца City сравнивается в алфавитном порядке с соответствующим значением столбца Location.

Самосоединение, или соединение таблицы самой с собой

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

Соединение таблицы с самой собой демонстрируется в примере ниже:

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

Здесь предложение FROM содержит два псевдонима для таблицы Department: t1 и t2. Первое условие в предложении WHERE определят столбцы соединения, а второе — удаляет ненужные дубликаты, обеспечивая сравнение каждого отдела с другими отделами.

Полусоединение

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

Результат выполнения запроса:

Как можно видеть, список выбора SELECT в полусоединении содержит только столбцы из таблицы Employee. Это и есть характерной особенностью операции полусоединения. Эта операция обычно применяется в распределенной обработке запросов, чтобы свести к минимуму объем передаваемых данных. Компонент Database Engine использует операцию полусоединения для реализации функциональности, называющейся соединением типа «звезда».

professorweb.ru

Перекрестное объединение (CROSS JOIN)

CROSS JOIN является базовым вариантом объединения и представляет собой декартово произведение (Cartesian product). Эта операция просто объединяет каждую строку первой таблицы с каждой строкой второй таблицы. Лучший пример, иллюстрирующий декартово произведение, представлен в Википедии. В этом примере мы получаем колоду карт, выполнив «перекрестное объединение» таблицы достоинств и таблицы мастей.

Виды join

В реальных сценариях операция CROSS JOIN может быть очень полезна при создании отчетов. Например, мы можем сгенерировать набор дат (например, дни в месяце) (days) и выполнить перекрестное объединение со всеми отделами (departments), имеющимися в базе данных. В результате мы получим полную таблицу день/отдел. Используя синтаксис PostgreSQL:

SELECT *    -- This just generates all the days in January 2017    FROM generate_series(      '2017-01-01'::TIMESTAMP,      '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',      INTERVAL '1 day'    ) AS days(day)        -- Here, we're combining all days with all departments    CROSS JOIN departments

Представим себе, что мы имеем следующие данные:

+--------+ +------------+  | day | | department |  +--------+ +------------+  | Jan 01 | | Dept 1 |  | Jan 02 | | Dept 2 |  | ... | | Dept 3 |  | Jan 30 | +------------+  | Jan 31 |  +--------+  

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

+--------+------------+  | day | department |  +--------+------------+  | Jan 01 | Dept 1 |  | Jan 01 | Dept 2 |  | Jan 01 | Dept 3 |    | Jan 02 | Dept 1 |  | Jan 02 | Dept 2 |  | Jan 02 | Dept 3 |  | ... | ... |  | Jan 31 | Dept 1 |  | Jan 31 | Dept 2 |  | Jan 31 | Dept 3 |  +--------+------------+  

Теперь для каждой комбинации день/отдел мы можем вычислить дневную выручку для данного отдела или другие аналогичные показатели.

Свойства

Как мы уже сказали, операция CROSS JOIN представляет собой декартово произведение. Соответственно, в математической нотации для описания данной операции используется знак умножения: A × B, или в нашем случае days × departments.

Как и в случае «обычного» арифметического умножения, если одна из двух таблиц пустая (имеет нулевой размер), результат также будет пустым. Это абсолютно логично. Если мы объединим 31 день и 0 отделов, мы получим 0 комбинаций день/отдел. Аналогично, если мы объединим пустой диапазон дат с любым количеством отделов, мы также получим 0 комбинаций день/отдел. Другими словами:

size(result) = size(days) * size(departments)

Альтернативный синтаксис

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

SELECT *    FROM      generate_series(        '2017-01-01'::TIMESTAMP,        '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',        INTERVAL '1 day'      ) AS days(day),      departments

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

Внутреннее объединение (INNER JOIN) или тета-объединение (THETA JOIN)

Развивая идею предыдущей операции CROSS JOIN, операция INNER JOIN (или просто JOIN, иногда также THETA JOIN) позволяет выполнять фильтрацию результата декартова произведения на основе некоторого предиката. Как правило, мы помещаем этот предикат в предложение ON. Таким образом, запрос принимает следующий вид:

SELECT *    -- Same as before    FROM generate_series(      '2017-01-01'::TIMESTAMP,      '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',      INTERVAL '1 day'    ) AS days(day)        -- Now, exclude all days/departments combinations for    -- days before the department was created    JOIN departments AS d ON day >= d.created_at

В большинстве СУБД ключевое слово INNER является необязательным, поэтому мы просто не указываем его.

Операция INNER JOIN позволяет нам использовать произвольные предикаты в предложении ON, что опять же очень удобно при создании отчетов. Аналогично CROSS JOIN мы объединяем все дни со всеми отделами, но потом оставляем только те комбинации день/отдел, для которых данный отдел уже существовал в данный день.

Используем те же исходные данные:

+--------+ +------------+------------+  | day | | department | created_at |  +--------+ +------------+------------+  | Jan 01 | | Dept 1 | Jan 10 |  | Jan 02 | | Dept 2 | Jan 11 |  | ... | | Dept 3 | Jan 12 |  | Jan 30 | +------------+------------+  | Jan 31 |  +--------+  

Получим следующий результат:

+--------+------------+  | day | department |  +--------+------------+  | Jan 10 | Dept 1 |    | Jan 11 | Dept 1 |  | Jan 11 | Dept 2 |    | Jan 12 | Dept 1 |  | Jan 12 | Dept 2 |  | Jan 12 | Dept 3 |    | Jan 13 | Dept 1 |  | Jan 13 | Dept 2 |  | Jan 13 | Dept 3 |  | ... | ... |  | Jan 31 | Dept 1 |  | Jan 31 | Dept 2 |  | Jan 31 | Dept 3 |  +--------+------------+  

Результат операции содержит данные, начиная с 10 января. Более ранние даты были отфильтрованы.

Свойства

Операция INNER JOIN представляет собой операцию CROSS JOIN с фильтрацией. Это означает, что если одна из таблиц пустая, то результат также гарантированно будет пустым. По причине наличия предиката, результат операции INNER JOIN может быть меньшего объема, чем результат операции CROSS JOIN. Другими словами:

size(result) <= size(days) * size(departments)

Альтернативный синтаксис

Несмотря на то, что предложение ON является обязательным для операции INNER JOIN, мы не обязаны указывать в нем предикат (хотя это крайне желательно в целях улучшения читаемости). Рассмотренный выше запрос эквивалентен следующему:

SELECT *    FROM generate_series(      '2017-01-01'::TIMESTAMP,      '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',      INTERVAL '1 day'    ) AS days(day)        -- You can always JOIN .. ON true (or 1 = 1 in other DBs)    -- to turn an syntactic INNER JOIN into a semantic CROSS JOIN    JOIN departments AS d ON true        -- ... and then turn the CROSS JOIN back into an INNER JOIN    -- by putting the JOIN predicate in the WHERE clause:    WHERE day >= d.created_at

Безусловно, это просто запутывание кода, но ведь у нас могут быть свои причины, не так ли? Сделав еще один шаг, мы можем написать следующий запрос, который также является эквивалентным, поскольку большинство оптимизаторов способны распознать равнозначность и выполнить INNER JOIN:

SELECT *    FROM generate_series(      '2017-01-01'::TIMESTAMP,      '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',      INTERVAL '1 day'    ) AS days(day)        -- Now, this is really a syntactic CROSS JOIN    CROSS JOIN departments AS d    WHERE day >= d.created_at

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

 

SELECT *    FROM      generate_series(        '2017-01-01'::TIMESTAMP,        '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',        INTERVAL '1 day'      ) AS days(day),      departments AS d    WHERE day >= d.created_at    

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

Объединение на основе равенства (EQUI JOIN)

Иногда в литературе встречается термин EQUI JOIN. На самом деле, «EQUI» не является ключевым словом SQL, а просто обозначает специальный вариант записи особого случая операции INNER JOIN.

Следует отметить, что не совсем правомерно называть EQUI JOIN особым случаем, поскольку эту операцию мы выполняем чаще всего в SQL и OLTP приложениях, когда просто объединяем таблицы на основе отношения первичного/внешнего ключа. Например:

SELECT *    FROM actor AS a    JOIN film_actor AS fa ON a.actor_id = fa.actor_id    JOIN film AS f ON f.film_id = fa.film_id

Представленный выше запрос извлекает всех актеров и фильмы, в которых они снимались. В нем присутствуют две операции INNER JOIN. Первая из них объединяет таблицу актеров actor и соответствующие записи из таблицы film_actor, содержащей информацию об отношениях фильм/актер (поскольку каждый актер может играть во множестве фильмов, а в каждом фильме может играть множество актеров). Вторая операция INNER JOIN выполняет объединение с таблицей film, содержащей информацию о фильмах.

Свойства

Данная операция имеет те же свойства, что и «обычная» операция INNER JOIN. То есть EQUI JOIN также является декартовым произведением (CROSS JOIN) с отфильтрованным результатом. В частности, в нашем случае результат содержит только те комбинации актер/фильм, для которых данный актер действительно играл в данном фильме. Таким образом, мы снова имеем соотношение:

size(result) <= size(actor) * size(film)

Объем результата может быть равен полному декартову произведению таблиц actor и film только в том случае, если каждый актер играл в каждом фильме, что маловероятно.

Альтернативный синтаксис: USING

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

SELECT *    FROM actor    JOIN film_actor USING (actor_id)    JOIN film USING (film_id)

Предложение USING заменяет предложение ON и позволяет указать набор столбцов, которые должны присутствовать в обеих объединяемых таблицах. Если наша база данных была хорошо спроектирована (как, например, база данных Sakila), то есть, если каждый внешний ключ имеет такое же имя, как и соответствующий первичный ключ (например, actor.actor_id = film_actor.actor_id), тогда мы можем использовать предложение USING для реализации операции EQUI JOIN, как минимум, в следующих СУБД:

  • Derby
  • Firebird
  • HSQLDB
  • Ingres
  • MariaDB
  • MySQL
  • Oracle
  • PostgreSQL
  • SQLite
  • Vertica

Следующие СУБД, к сожалению, не поддерживают данный синтаксис:

  • Access
  • Cubrid
  • DB2
  • H2
  • HANA
  • Informix
  • SQL Server
  • Sybase ASE
  • Sybase SQL Anywhere

Запрос с предложением USING (почти) идентичен запросу с предложением ON, однако значительно более удобен для написания и восприятия. Мы сказали «почти», потому что согласно спецификации некоторых СУБД (и стандарту SQL) столбец, используемый в предложении USING, не должен иметь квалификатор. Например:

SELECT      f.title,   -- Ordinary column, can be qualified      f.film_id, -- USING column, shouldn't be qualified      film_id    -- USING column, correct / non-ambiguous here    FROM actor AS a    JOIN film_actor AS fa USING (actor_id)    JOIN film AS f USING (film_id)

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

CREATE TABLE film (      ..      language_id          BIGINT REFERENCES language,      original_language_id BIGINT REFERENCES language,    )

Если мы хотим выполнить объединение по original_language_id, нам придется использовать предложение ON.

Альтернативный синтаксис: Естественное объединение (NATURAL JOIN)

Более экстремальным и значительно менее полезным вариантом синтаксиса операции EQUI JOIN является синтаксис на основе предложения NATURAL JOIN. Рассмотренный выше синтаксис на основе USING можно «улучшить», заменив USING на NATURAL JOIN следующим образом:

SELECT *    FROM actor    NATURAL JOIN film_actor    NATURAL JOIN film

Обратите внимание, в этом запросе нет необходимости указывать какие-либо критерии объединения, поскольку предложение NATURAL JOIN автоматически определяет столбцы, имеющие одинаковые имена в обеих объединяемых таблица, и помещает их в «скрытое» предложение USING. Если  первичные и внешние ключи имеют одинаковые имена, этот подход может показаться полезным, однако это не так.

В базе данных Sakila, каждая таблица имеет столбец last_update, который автоматически используется предложением NATURAL JOIN. Таким образом, запрос NATURAL JOIN эквивалентен следующему запросу, который, конечно же, не имеет никакого смысла:

SELECT *    FROM actor    JOIN film_actor USING (actor_id, last_update)    JOIN film USING (film_id, last_update)

Итак, сразу же забудьте о NATURAL JOIN и никогда не используйте этот вариант (за исключением очень редких случаев, таких как объединение диагностических представлений Oracle, например, v$sql NATURAL JOIN v$sql_plan, в целях специализированной аналитики).

datareview.info

Выборки данных из таблиц

Если рассматривать задачу выбора данных или построения некоторого отчета, можно определить уровень сложности данной операции. Как правило, при работе с серьезными (по объему информации) базами данных, которые формируются, например, в интернет-магазинах или крупных компаниях, выборка данных не будет ограничиваться лишь одной таблицей. Как правило, выборки могут быть из довольно большого количества не только связанных между собой таблиц, но и вложенных запросов/подзапросов, которые составляет сам программист, в зависимости от поставленной перед ним задачи. Для выборки из одной таблицы можно использовать простейшую конструкцию:

Select * from Person

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

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

Способы подключения дополнительных таблиц

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

  1. Оператор Inner Join.
  2. Left Join или, это второй способ записи, Left Outer Join.
  3. Cross Join.
  4. Full Join.

Использование операторов объединения таблиц на практике можно усвоить, рассмотрев применение оператора SQL — Inner Join. Пример его использования будет выглядеть следующим образом:

Select * from Person

Inner join Subdivision on Su_Person = Pe_ID

Язык SQL и оператор Join Inner Join можно использовать не только для объединения двух и более таблиц, но и для подключения иных подзапросов, что значительно облегчает работу администраторов базы данных и, как правило, может значительно ускорить выполнение определенных, сложных по структуре запросов.

Объединение данных в таблицах построчно

оператор sql inner join примеры

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

Применение этих конструкций будет зависеть от поставленной перед разработчиком задачи и результата, которого он хочет достичь в итоге.

Описание оператора Inner Join

В большинстве случаев для объединения нескольких таблиц в языке SQL используется оператор Inner Join. Описание Inner Join в SQL довольно простое для понимания среднестатистического программиста, который только начинает разбираться в базах данных. Если рассмотреть описание механизма работы этой конструкции, то получим следующую картину. Логика оператора в целом построена на возможности пересечения и выборки только тех данных, которые есть в каждой из входящих в запрос таблиц.

Если рассмотреть такую работу с точки зрения графической интерпретации, то получим структуру оператора SQL Inner Join, пример которой можно показать с помощью следующей схемы:

sql inner join синтаксис примеры

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

Синтаксис оператора Inner Join

Как уже говорилось ранее, оператор Inner Join, а именно его синтаксис, необычайно прост. Для организации связей между таблицами в пределах одной выборки достаточно будет запомнить и использовать следующую принципиальную схему построения оператора, которая прописывается в одну строчку программного SQL-кода, а именно:

  • Inner Join [Имя таблицы] on [ключевое поле из таблицы, к которой подключаем] = [Ключевому полю подключаемой таблицы].

Для связи в данном операторе используются главные ключи таблиц. Как правило, в группе таблиц, которые хранят информацию о сотрудниках, ранее описанные Person и Subdivision имеют хотя бы по одной похожей записи. Итак, рассмотрим подробнее оператор SQL Inner Join, пример которого был показан несколько ранее.

Пример и описание подключения к выборке одной таблицы

У нас есть таблица Person, где хранится информация обо всех сотрудниках, работающих в компании. Сразу отметим, что главным ключем данной таблицы является поле – Pe_ID. Как раз по нему и будет идти связка.

Вторая таблица Subdivision будет хранить информацию о подразделениях, в которых работают сотрудники. Она, в свою очередь, связана с помощью поля Su_Person с таблицей Person. О чем это говорит? Исходя из схемы данных можно сказать, что в таблице подразделений для каждой записи из таблицы «Сотрудники» будет информация об отделе, в котором они работают. Именно по этой связи и будет работать оператор Inner Join.

Для более понятного использования рассмотрим оператор SQL Inner Join (примеры его использования для одной и двух таблиц). Если рассматривать пример для одной таблицы, то тут все довольно просто:

Select * from Person

Inner join Subdivision on Su_Person = Pe_ID

Пример подключения двух таблиц и подзапроса

sql и оператор join inner join

Оператор SQL Inner Join, примеры использования которого для выборки данных из нескольких таблиц можно организовать вышеуказанным образом, работает по чуть усложненному принципу. Для двух таблиц усложним задачу. Скажем, у нас есть таблица Depart, в которой хранится информация обо всех отделах в каждом из подразделений. В в эту таблицу записан номер подразделения и номер сотрудника и нужно дополнить выборку данных названием каждого отдела. Забегая вперед, стоит сказать, что для решения этой задачи можно воспользоваться двумя методами.

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

Select Pe_ID, Pe_Name, Su_Id, Su_Name, Dep_ID, Dep_Name from Person

Inner join Subdivision on Su_Person = Pe_ID

Inner join Depart on Su_Depart = Dep_ID and Pe_Depart = Dep_ID

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

Select Pe_ID, Pe_Name, Su_Id, Su_Name, Dep_ID, Dep_Name from Person

Inner join Subdivision on Su_Person = Pe_ID

Inner join (Select Dep_ID, Dep_Name, Pe_Depart from Depart) as T on Su_Depart = Dep_ID and Pe_Depart = Dep_ID

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

Пример использования оператора Inner Join для выборок из большого количества таблиц

Построение сложных запросов подразумевает использование для выборки данных значительного количества таблиц и подзапросов, связанных между собой. Этим требованиям может удовлетворить SQL Inner Join синтаксис. Примеры использования оператора в данном случаем могут усложняться не только выборками из многих мест хранения данных, но и с большого количества вложенных подзапросов. Для конкретного примера можно взять выборку данных из системных таблиц (оператор Inner Join SQL). Пример — 3 таблицы — в этом случае будет иметь довольно сложную структуру.

inner join sql пример 3 таблицы

В данном случае подключено (к основной таблице) еще три дополнительно и введено несколько условий выбора данных.

При использовании оператора Inner Join стоит помнить о том, что чем сложнее запрос, тем дольше он будет реализовываться, поэтому стоит искать пути более быстрого выполнения и решения поставленной задачи.inner join sql пример 3 таблицы

Заключение

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

fb.ru

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

Существует несколько вариантов запроса JOIN, начнём мы с самого популярного, а именно INNER JOIN:

SELECT * FROM `users` INNER JOIN `subscribers` ON `users`.`email` = `subscribers`.`email`

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

Особенностью INNER JOIN является то, что в результат входят все поля со всеми значениями. Количество записей ровно столько, сколько удовлетворили условиям у обеих таблиц.

Теперь давайте перейдём к следующей разновидности JOIN, а точнее к LEFT OUTER JOIN:

SELECT * FROM `users` LEFT OUTER JOIN `subscribers` ON `users`.`email` = `subscribers`.`email`

Особенностью данного запроса является то, что результат выборки содержит записи, удовлетворяющие левой таблице. Если они ещё и удовлетворяют условиям правой таблицы, то это идентично INNER JOIN, иначе вместо значений в правой таблице будет NULL.

Теперь перейдём к RIGHT OUTER JOIN:

SELECT * FROM `users` RIGHT OUTER JOIN `subscribers` ON `users`.`email` = `subscribers`.`email`

Зеркальная противоположность LEFT OUTER JOIN, теперь NULL присутствуют в первой таблице, то есть слева.

И, наконец, последний тип JOIN — это CROSS JOIN:

SELECT * FROM `users` CROSS JOIN `subscribers`

Данный запрос выдаёт всевозможные сочетания двух таблиц. В данном запросе результирующее число записей — это перемножение количества записей в обеих таблицах.

Я ещё не рассказал о FULL OUTER JOIN, который не поддерживается MySQL. Но, на мой взгляд, он и не нужен. Его особенностью является то, что он выводит строку, в которой есть хотя бы одно совпадение с любой из таблиц. Соответственно, в другой таблице (в которой нет совпадения с условием) идут NULL. Фактически, это объединение LEFT OUTER JOIN и RIGHT OUTER JOIN:

SELECT * FROM `users` LEFT OUTER JOIN `subscribers` ON `users`.`email` = `subscribers`.`email` UNION SELECT * FROM `users` RIGHT OUTER JOIN `subscribers` ON `users`.`email` = `subscribers`.`email`

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

myrusakov.ru

Написать запросы SQL с JOIN самостоятельно, а затем посмотреть решения

Есть база данных «Театр». Таблица Play содержит данные о постановках. Таблица Team — о ролях актёров. Таблица Actor — об актёрах. Таблица Director — о режиссёрах. Поля таблиц, первичные и внешние ключи можно увидеть на рисунке ниже (для увеличения нажать левой кнопкой мыши).

Виды join

Псевдонимы соединяемых таблиц

В предыдущих запросах мы указывали с названиями извлекаемых столбцов из разных таблиц полные имена этих таблиц. Такие запросы выглядят громоздко: одно и то же слово повторяется несколько раз. Нельзя ли как-то упростить конструкцию? Оказывается, можно. Для этого следует использовать псевдонимы таблиц — их сокращённые имена. Псевдоним может состоять и из одной буквы. Возможно любое количество букв в псевдониме, главное, чтобы запрос после сокращения был понятен Вам самим. Общее правило: в секции запроса, определяющей соединение, то есть вокруг слова JOIN нужно указать полные имена таблиц, а за каждым именем должен следовать псевдоним таблицы.

JOIN и соединение более двух таблиц

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

CROSS JOIN (перекрестное соединение)

Использование оператора SQL CROSS JOIN в наиболее простой форме — без условия соединения — реализует операцию декартова произведения в реляционной алгебре. Результатом такого соединения будет сцепление каждой строки первой таблицы с каждой строкой второй таблицы. Таблицы могут быть записаны в запросе либо через оператор CROSS JOIN, либо через запятую между ними.

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

Но для CROSS JOIN можно задать условие соединения! Результат будет совсем иным. При использовании оператора «запятая» вместо явного указания CROSS JOIN условие соединения задаётся не словом ON, а словом WHERE.

И это совпадение не случайно. Запрос c перекрестным соединением по условию соединения полностью аналогичен запросу с внутренним соединением — INNER JOIN — или, учитывая, что слово INNER — не обязательное, просто JOIN.

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

Поделиться с друзьями

function-x.ru

You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.