Соединение таблиц
Содержание:
JOIN и соединение более двух таблиц
Реляционные базы данных должны подчиняться требованиям целостности и неизбыточности данных,
в связи с чем данные об одном бизнес-процессе могут содержаться не только в одной, двух, но и в трёх и более
таблицах. В этих случаях для анализа данных используются цепочки соединённых таблиц: например, в одной (первой)
таблице содержится некоторый количественный показатель, вторую таблицу с первой и третьей связывают
внешние ключи — данные пересекаются, но только третья таблица содержит условие, в зависимости от которого
может быть выведен количественный показатель из первой таблицы. И таблиц может быть ещё больше. При помощи оператора
SQL JOIN в одном запросе можно соединить большое число таблиц. В таких запросах за одной секцией соединения
следует другая, причём каждый следующий JOIN соединяет со следующей таблицей таблицу, которая была второй
в предыдущем звене цепочки. Таким образом, синтаксис SQL запроса для соединения более двух таблиц следующий:
   SELECT ИМЕНА_СТОЛБЦОВ (1..N)
      FROM ИМЯ_ТАБЛИЦЫ_1 JOIN ИМЯ_ТАБЛИЦЫ_2
	  ON УСЛОВИЕ
	  JOIN ИМЯ_ТАБЛИЦЫ_3
	     ON УСЛОВИЕ
	  …
      JOIN ИМЯ_ТАБЛИЦЫ_M
	     ON УСЛОВИЕ	  
Пример 8.  База данных — та же, что и в предыдущих примерах. К таблицам
Categories и Parts в этом примере добавится таблица Ads, содержащая данные об опубликованных на портале объявлениях.
Приведём фрагмент таблицы Ads, в котором среди записей есть записи о тех объявлениях, срок публикации которых
истекает 2018-04-02.
| A_Id | Part_ID | Date_start | Date_end | Text | 
| 21 | 1 | ‘2018-02-11’ | ‘2018-04-20’ | «Продаю…» | 
| 22 | 1 | ‘2018-02-11’ | ‘2018-05-12’ | «Продаю…» | 
| … | … | … | … | … | 
| 27 | 1 | ‘2018-02-11’ | ‘2018-04-02’ | «Продаю…» | 
| 28 | 2 | ‘2018-02-11’ | ‘2018-04-21’ | «Продаю…» | 
| 29 | 2 | ‘2018-02-11’ | ‘2018-04-02’ | «Продаю…» | 
| 30 | 3 | ‘2018-02-11’ | ‘2018-04-22’ | «Продаю…» | 
| 31 | 4 | ‘2018-02-11’ | ‘2018-05-02’ | «Продаю…» | 
| 32 | 4 | ‘2018-02-11’ | ‘2018-04-13’ | «Продаю…» | 
| 33 | 3 | ‘2018-02-11’ | ‘2018-04-12’ | «Продаю…» | 
| 34 | 4 | ‘2018-02-11’ | ‘2018-04-23’ | «Продаю…» | 
Представим, что сегодня ‘2018-04-02’, то есть это значение принимает функция CURDATE() —
текущая дата. Требуется узнать, к каким категориям принадлежат объявления, срок публикации которых
истекает сегодня. Названия категорий есть только в таблице CATEGORIES, а даты истечения срока публикации объявлений
— только в таблице ADS. В таблице PARTS — части категорий (или проще, подкатегории) опубликованных объявлений.
Но внешним ключом Cat_ID таблица PARTS связана с таблицей CATEGORIES, а таблица ADS связана внешним
ключом Part_ID с таблицей PARTS. Поэтому соединяем в одном запросе три таблицы и этот запрос можно
с максимальной корректностью назвать цепочкой.
Запрос будет следующим:
    SELECT C.Cat_name FROM Categories C JOIN Parts P
	ON P.Cat=C.Catnumb JOIN ads A ON A.Part_id=P.Part_id
	WHERE A.Date_end=CURDATE()
Результат запроса — таблица, содержащая названия двух категорий — «Недвижимость» и
«Транспорт»:
| Cat_name | 
| Недвижимость | 
| Транспорт | 
Внешнее соединение
В предшествующих примерах естественного соединения, результирующий набор содержал только те строки с одной таблицы, для которых имелись соответствующие строки в другой таблице. Но иногда кроме совпадающих строк бывает необходимым извлечь из одной или обеих таблиц строки без совпадений. Такая операция называется внешним соединением (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, которые не отвечают условию в естественном соединении.
SQL References
SQL Keywords
  ADD
  ADD CONSTRAINT
  ALTER
  ALTER COLUMN
  ALTER TABLE
  ALL
  AND
  ANY
  AS
  ASC
  BACKUP DATABASE
  BETWEEN
  CASE
  CHECK
  COLUMN
  CONSTRAINT
  CREATE
  CREATE DATABASE
  CREATE INDEX
  CREATE OR REPLACE VIEW
  CREATE TABLE
  CREATE PROCEDURE
  CREATE UNIQUE INDEX
  CREATE VIEW
  DATABASE
  DEFAULT
  DELETE
  DESC
  DISTINCT
  DROP
  DROP COLUMN
  DROP CONSTRAINT
  DROP DATABASE
  DROP DEFAULT
  DROP INDEX
  DROP TABLE
  DROP VIEW
  EXEC
  EXISTS
  FOREIGN KEY
  FROM
  FULL OUTER JOIN
  GROUP BY
  HAVING
  IN
  INDEX
  INNER JOIN
  INSERT INTO
  INSERT INTO SELECT
  IS NULL
  IS NOT NULL
  JOIN
  LEFT JOIN
  LIKE
  LIMIT
  NOT
  NOT NULL
  OR
  ORDER BY
  OUTER JOIN
  PRIMARY KEY
  PROCEDURE
  RIGHT JOIN
  ROWNUM
  SELECT
  SELECT DISTINCT
  SELECT INTO
  SELECT TOP
  SET
  TABLE
  TOP
  TRUNCATE TABLE
  UNION
  UNION ALL
  UNIQUE
  UPDATE
  VALUES
  VIEW
  WHERE
MySQL Functions
  String Functions
  ASCII
  CHAR_LENGTH
  CHARACTER_LENGTH
  CONCAT
  CONCAT_WS
  FIELD
  FIND_IN_SET
  FORMAT
  INSERT
  INSTR
  LCASE
  LEFT
  LENGTH
  LOCATE
  LOWER
  LPAD
  LTRIM
  MID
  POSITION
  REPEAT
  REPLACE
  REVERSE
  RIGHT
  RPAD
  RTRIM
  SPACE
  STRCMP
  SUBSTR
  SUBSTRING
  SUBSTRING_INDEX
  TRIM
  UCASE
  UPPER
Numeric Functions
  ABS
  ACOS
  ASIN
  ATAN
  ATAN2
  AVG
  CEIL
  CEILING
  COS
  COT
  COUNT
  DEGREES
  DIV
  EXP
  FLOOR
  GREATEST
  LEAST
  LN
  LOG
  LOG10
  LOG2
  MAX
  MIN
  MOD
  PI
  POW
  POWER
  RADIANS
  RAND
  ROUND
  SIGN
  SIN
  SQRT
  SUM
  TAN
  TRUNCATE
Date Functions
  ADDDATE
  ADDTIME
  CURDATE
  CURRENT_DATE
  CURRENT_TIME
  CURRENT_TIMESTAMP
  CURTIME
  DATE
  DATEDIFF
  DATE_ADD
  DATE_FORMAT
  DATE_SUB
  DAY
  DAYNAME
  DAYOFMONTH
  DAYOFWEEK
  DAYOFYEAR
  EXTRACT
  FROM_DAYS
  HOUR
  LAST_DAY
  LOCALTIME
  LOCALTIMESTAMP
  MAKEDATE
  MAKETIME
  MICROSECOND
  MINUTE
  MONTH
  MONTHNAME
  NOW
  PERIOD_ADD
  PERIOD_DIFF
  QUARTER
  SECOND
  SEC_TO_TIME
  STR_TO_DATE
  SUBDATE
  SUBTIME
  SYSDATE
  TIME
  TIME_FORMAT
  TIME_TO_SEC
  TIMEDIFF
  TIMESTAMP
  TO_DAYS
  WEEK
  WEEKDAY
  WEEKOFYEAR
  YEAR
  YEARWEEK
Advanced Functions
  BIN
  BINARY
  CASE
  CAST
  COALESCE
  CONNECTION_ID
  CONV
  CONVERT
  CURRENT_USER
  DATABASE
  IF
  IFNULL
  ISNULL
  LAST_INSERT_ID
  NULLIF
  SESSION_USER
  SYSTEM_USER
  USER
  VERSION
SQL Server Functions
  String Functions
  ASCII
  CHAR
  CHARINDEX
  CONCAT
  Concat with +
  CONCAT_WS
  DATALENGTH
  DIFFERENCE
  FORMAT
  LEFT
  LEN
  LOWER
  LTRIM
  NCHAR
  PATINDEX
  QUOTENAME
  REPLACE
  REPLICATE
  REVERSE
  RIGHT
  RTRIM
  SOUNDEX
  SPACE
  STR
  STUFF
  SUBSTRING
  TRANSLATE
  TRIM
  UNICODE
  UPPER
Numeric Functions
  ABS
  ACOS
  ASIN
  ATAN
  ATN2
  AVG
  CEILING
  COUNT
  COS
  COT
  DEGREES
  EXP
  FLOOR
  LOG
  LOG10
  MAX
  MIN
  PI
  POWER
  RADIANS
  RAND
  ROUND
  SIGN
  SIN
  SQRT
  SQUARE
  SUM
  TAN
Date Functions
  CURRENT_TIMESTAMP
  DATEADD
  DATEDIFF
  DATEFROMPARTS
  DATENAME
  DATEPART
  DAY
  GETDATE
  GETUTCDATE
  ISDATE
  MONTH
  SYSDATETIME
  YEAR
Advanced Functions
  CAST
  COALESCE
  CONVERT
  CURRENT_USER
  IIF
  ISNULL
  ISNUMERIC
  NULLIF
  SESSION_USER
  SESSIONPROPERTY
  SYSTEM_USER
  USER_NAME
MS Access Functions
  String Functions
  Asc
  Chr
  Concat with &
  CurDir
  Format
  InStr
  InstrRev
  LCase
  Left
  Len
  LTrim
  Mid
  Replace
  Right
  RTrim
  Space
  Split
  Str
  StrComp
  StrConv
  StrReverse
  Trim
  UCase
Numeric Functions
  Abs
  Atn
  Avg
  Cos
  Count
  Exp
  Fix
  Format
  Int
  Max
  Min
  Randomize
  Rnd
  Round
  Sgn
  Sqr
  Sum
  Val
Date Functions
  Date
  DateAdd
  DateDiff
  DatePart
  DateSerial
  DateValue
  Day
  Format
  Hour
  Minute
  Month
  MonthName
  Now
  Second
  Time
  TimeSerial
  TimeValue
  Weekday
  WeekdayName
  Year
Other Functions
  CurrentUser
  Environ
  IsDate
  IsNull
  IsNumeric
SQL Quick Ref
SQL Справочник
SQL Ключевые слова
  ADD
  ADD CONSTRAINT
  ALTER
  ALTER COLUMN
  ALTER TABLE
  ALL
  AND
  ANY
  AS
  ASC
  BACKUP DATABASE
  BETWEEN
  CASE
  CHECK
  COLUMN
  CONSTRAINT
  CREATE
  CREATE DATABASE
  CREATE INDEX
  CREATE OR REPLACE VIEW
  CREATE TABLE
  CREATE PROCEDURE
  CREATE UNIQUE INDEX
  CREATE VIEW
  DATABASE
  DEFAULT
  DELETE
  DESC
  DISTINCT
  DROP
  DROP COLUMN
  DROP CONSTRAINT
  DROP DATABASE
  DROP DEFAULT
  DROP INDEX
  DROP TABLE
  DROP VIEW
  EXEC
  EXISTS
  FOREIGN KEY
  FROM
  FULL OUTER JOIN
  GROUP BY
  HAVING
  IN
  INDEX
  INNER JOIN
  INSERT INTO
  INSERT INTO SELECT
  IS NULL
  IS NOT NULL
  JOIN
  LEFT JOIN
  LIKE
  LIMIT
  NOT
  NOT NULL
  OR
  ORDER BY
  OUTER JOIN
  PRIMARY KEY
  PROCEDURE
  RIGHT JOIN
  ROWNUM
  SELECT
  SELECT DISTINCT
  SELECT INTO
  SELECT TOP
  SET
  TABLE
  TOP
  TRUNCATE TABLE
  UNION
  UNION ALL
  UNIQUE
  UPDATE
  VALUES
  VIEW
  WHERE
MySQL Функции
Функции строк
ASCII
CHAR_LENGTH
CHARACTER_LENGTH
CONCAT
CONCAT_WS
FIELD
FIND_IN_SET
FORMAT
INSERT
INSTR
LCASE
LEFT
LENGTH
LOCATE
LOWER
LPAD
LTRIM
MID
POSITION
REPEAT
REPLACE
REVERSE
RIGHT
RPAD
RTRIM
SPACE
STRCMP
SUBSTR
SUBSTRING
SUBSTRING_INDEX
TRIM
UCASE
UPPER
Функции чисел
ABS
ACOS
ASIN
ATAN
ATAN2
AVG
CEIL
CEILING
COS
COT
COUNT
DEGREES
DIV
EXP
FLOOR
GREATEST
LEAST
LN
LOG
LOG10
LOG2
MAX
MIN
MOD
PI
POW
POWER
RADIANS
RAND
ROUND
SIGN
SIN
SQRT
SUM
TAN
TRUNCATE
Функции дат
ADDDATE
ADDTIME
CURDATE
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURTIME
DATE
DATEDIFF
DATE_ADD
DATE_FORMAT
DATE_SUB
DAY
DAYNAME
DAYOFMONTH
DAYOFWEEK
DAYOFYEAR
EXTRACT
FROM_DAYS
HOUR
LAST_DAY
LOCALTIME
LOCALTIMESTAMP
MAKEDATE
MAKETIME
MICROSECOND
MINUTE
MONTH
MONTHNAME
NOW
PERIOD_ADD
PERIOD_DIFF
QUARTER
SECOND
SEC_TO_TIME
STR_TO_DATE
SUBDATE
SUBTIME
SYSDATE
TIME
TIME_FORMAT
TIME_TO_SEC
TIMEDIFF
TIMESTAMP
TO_DAYS
WEEK
WEEKDAY
WEEKOFYEAR
YEAR
YEARWEEK
Функции расширений
BIN
BINARY
CASE
CAST
COALESCE
CONNECTION_ID
CONV
CONVERT
CURRENT_USER
DATABASE
IF
IFNULL
ISNULL
LAST_INSERT_ID
NULLIF
SESSION_USER
SYSTEM_USER
USER
VERSION
SQL Server функции
Функции строк
ASCII
CHAR
CHARINDEX
CONCAT
Concat with +
CONCAT_WS
DATALENGTH
DIFFERENCE
FORMAT
LEFT
LEN
LOWER
LTRIM
NCHAR
PATINDEX
QUOTENAME
REPLACE
REPLICATE
REVERSE
RIGHT
RTRIM
SOUNDEX
SPACE
STR
STUFF
SUBSTRING
TRANSLATE
TRIM
UNICODE
UPPER
Функции чисел
ABS
ACOS
ASIN
ATAN
ATN2
AVG
CEILING
COUNT
COS
COT
DEGREES
EXP
FLOOR
LOG
LOG10
MAX
MIN
PI
POWER
RADIANS
RAND
ROUND
SIGN
SIN
SQRT
SQUARE
SUM
TAN
Функции дат
CURRENT_TIMESTAMP
DATEADD
DATEDIFF
DATEFROMPARTS
DATENAME
DATEPART
DAY
GETDATE
GETUTCDATE
ISDATE
MONTH
SYSDATETIME
YEAR
Функции расширений
CAST
COALESCE
CONVERT
CURRENT_USER
IIF
ISNULL
ISNUMERIC
NULLIF
SESSION_USER
SESSIONPROPERTY
SYSTEM_USER
USER_NAME
MS Access функции
Функции строк
Asc
Chr
Concat with &
CurDir
Format
InStr
InstrRev
LCase
Left
Len
LTrim
Mid
Replace
Right
RTrim
Space
Split
Str
StrComp
StrConv
StrReverse
Trim
UCase
Функции чисел
Abs
Atn
Avg
Cos
Count
Exp
Fix
Format
Int
Max
Min
Randomize
Rnd
Round
Sgn
Sqr
Sum
Val
Функции дат
Date
DateAdd
DateDiff
DatePart
DateSerial
DateValue
Day
Format
Hour
Minute
Month
MonthName
Now
Second
Time
TimeSerial
TimeValue
Weekday
WeekdayName
Year
Другие функции
CurrentUser
Environ
IsDate
IsNull
IsNumeric
SQL ОператорыSQL Типы данныхSQL Краткий справочник
CROSS JOIN (перекрестное соединение)
Использование оператора SQL CROSS JOIN в наиболее простой форме — без условия соединения —
реализует операцию .
Результатом такого соединения будет сцепление каждой строки первой таблицы с каждой строкой второй таблицы. Таблицы
могут быть записаны в запросе либо через оператор CROSS JOIN, либо через запятую между ними.
Пример 9.  База данных — всё та же, таблицы — Categories и Parts.
Реализовать операцию декартова произведения этих двух таблиц.
Запрос будет следующим:
SELECT (*) Categories CROSS JOIN Parts
Или без явного указания CROSS JOIN — через запятую:
SELECT (*) Categories, Parts
Запрос вернёт таблицу из 5 * 5 = 25 строк, фрагмент которой приведён ниже:
| Catnumb | Cat_name | Price | Part_ID | Part | Cat | 
| 10 | Стройматериалы | 105,00 | 1 | Квартиры | 505 | 
| 10 | Стройматериалы | 105,00 | 2 | Автомашины | 205 | 
| 10 | Стройматериалы | 105,00 | 3 | Доски | 10 | 
| 10 | Стройматериалы | 105,00 | 4 | Шкафы | 30 | 
| 10 | Стройматериалы | 105,00 | 5 | Книги | 160 | 
| … | … | … | … | … | … | 
| 45 | Техника | 65,00 | 1 | Квартиры | 505 | 
| 45 | Техника | 65,00 | 2 | Автомашины | 205 | 
| 45 | Техника | 65,00 | 3 | Доски | 10 | 
| 45 | Техника | 65,00 | 4 | Шкафы | 30 | 
| 45 | Техника | 65,00 | 5 | Книги | 160 | 
Как видно из примера, если результат такого запроса и имеет какую-либо ценность, то
это, возможно, наглядная ценность в некоторых случаях, когда не требуется вывести структурированную информацию,
тем более, даже самую простейшую аналитическую выборку. Кстати, можно указать выводимые столбцы из каждой
таблицы, но и тогда информационная ценность такого запроса не повысится.
Но для CROSS JOIN можно задать условие соединения! Результат будет совсем иным. При
использовании оператора «запятая» вместо явного указания CROSS JOIN условие соединения задаётся не
словом ON, а словом WHERE.
Пример 10.  Та же база данных портала объявлений, таблицы Categories и Parts.
Используя перекрестное соединение, соединить таблицы так, чтобы данные полностью пересекались по
условию. Условие — совпадение идентификатора категории в таблице Categories и ссылки на категорию в таблице Parts.
Запрос будет следующим:
   SELECT P.Part, C.Catnumb AS Cat, C.Price
      FROM Parts P, Categories C
	     WHERE P.Cat = C.Cat_ID
Запрос вернёт то же самое, что и запрос в примере 1:
| Part | Cat | Price | 
| Квартиры | 505 | 210,00 | 
| Автомашины | 205 | 160,00 | 
| Доски | 10 | 105,00 | 
| Шкафы | 30 | 77,00 | 
И это совпадение не случайно. Запрос c перекрестным соединением по условию соединения полностью
аналогичен запросу с внутренним соединением — INNER JOIN — или, учитывая, что слово INNER — не обязательное,
просто JOIN. 
Таким образом, какой вариант запроса использовать — вопрос стиля или даже привычки
специалиста по работе с базой данных. Возможно, перекрёстное соединение с условием для двух таблиц
может представляться более компактным. Но преимущество перекрестного соединения для более чем двух
таблиц (это также возможно) весьма спорно. В этом случае WHERE-условия пересечения перечисляются через
слово AND. Такая конструкция может быть громоздкой и трудной для чтения, если в конце запроса есть
также секция WHERE с условиями выборки.
Поделиться с друзьями
Реляционные базы данных и язык SQL
Example of SQL Left Join
To get company name and company id columns from company table and company id, item name, item unit columns from foods table, after an OUTER JOINING with these mentioned tables, the following SQL statement can be used :
Sample table: foods
Sample table: company
SQL Code:
Explanation:
This SQL statement would return all rows from the company table and only those rows from the foods table where the joined fields are equal and if the ON clause matches no records in the ‘foods’ table, the join will still return rows, but the NULL in each column of the right table.
Output:
COMPANY_ID COMPANY_NAME COMPANY_CITY COMPANY_ID ITEM_NAME ---------- ------------------------- ------------------------- ---------- -------------- 16 Akas Foods Delhi 16 Chex Mix 15 Jack Hill Ltd London 15 Cheez-It 15 Jack Hill Ltd London 15 BN Biscuit 17 Foodies. London 17 Mighty Munch 15 Jack Hill Ltd London 15 Pot Rice 18 Order All Boston 18 Jaffa Cakes 19 sip-n-Bite. New York
Pictorial Presentation of the above example:
Пример
Ниже приведен пример Oracle FULL OUTER JOIN:
Oracle PL/SQL
SELECT suppliers.supplier_id,
       suppliers.supplier_name,
       orders.order_date
  FROM suppliers
  FULL OUTER JOIN orders
    ON suppliers.supplier_id = orders.supplier_id;
| 1 | SELECTsuppliers.supplier_id, suppliers.supplier_name, orders.order_date FROMsuppliers FULLOUTERJOINorders ONsuppliers.supplier_id=orders.supplier_id; | 
Этот пример FULL OUTER JOIN возвратит все строки из таблицы suppliers и все строки из таблицы orders и всякий раз, когда условие соединения не выполняется, то поля в результирующем наборе будут принимать значения NULL.
Если значение поля supplier_id в таблице suppliers не существует в таблице orders, то все поля в таблице orders будут отображаться в результирующем наборе как NULL. Если значение supplier_id в таблице orders не существует в таблице suppliers, то все поля в таблице suppliers будут отображаться результирующем наборе как NULL .
Рассмотрим некоторые данные, чтобы понять, как работает FULL OUTER JOIN:
У нас есть таблица suppliers с двумя полями (supplier_id и supplier_name). Она содержит следующие данные:
| supplier_id | supplier_name | 
|---|---|
| 10000 | IBM | 
| 10001 | Hewlett Packard | 
| 10002 | Microsoft | 
| 10003 | NVIDIA | 
У нас есть вторая таблица orders с тремя полями (order_id, supplier_id и order_date), которая содержит следующие данные:
| order_id | supplier_id | order_date | 
|---|---|---|
| 500125 | 10000 | 12.05.2016 | 
| 500126 | 10001 | 14.05.2016 | 
| 500127 | 10004 | 18.05.2016 | 
Если мы выполним Oracle оператор SELECT (который содержит FULL OUTER JOIN) ниже:
Oracle PL/SQL
SELECT suppliers.supplier_id,
       suppliers.supplier_name,
       orders.order_date
  FROM suppliers
  FULL OUTER JOIN orders
    ON suppliers.supplier_id = orders.supplier_id;
| 1 | SELECTsuppliers.supplier_id, suppliers.supplier_name, orders.order_date FROMsuppliers FULLOUTERJOINorders ONsuppliers.supplier_id=orders.supplier_id; | 
Результирующий набор будет выглядеть следующим образом:
| supplier_id | supplier_name | order_date | 
|---|---|---|
| 10000 | IBM | 12.05.2016 | 
| 10001 | Hewlett Packard | 14.05.2016 | 
| 10002 | Microsoft | null | 
| 10003 | NVIDIA | null | 
| null | null | 18.05.2016 | 
Строки для Microsoft и NVIDIA будут включены, так как используется FULL OUTER JOIN. Тем не менее, вы заметите, что поле order_date для этих записей содержит значение NULL.
Строка для supplier_id 10004 также будет включена, так как используется FULL OUTER JOIN. Тем не менее, вы заметите, что supplier_id и поле supplier_name для этих записей содержат значение NULL.
SQL FULL OUTER JOIN
Другой тип объединения называется SQL FULL OUTER JOIN. Этот тип объединения возвращает все строки из LEFT таблицы и RIGHT таблицы со значениями NULL в месте, где условие соединения не выполняется.
Синтаксис
Синтаксис для SQL FULL OUTER JOIN:
SELECT columns
  FROM table1
  FULL  JOIN table2
    ON table1.column = table2.column;
В некоторых базах данных ключевое слово OUTER опускается и записывается просто как FULL JOIN.
Рисунок
На этом рисунке SQL FULL OUTER JOIN возвращает затененную область:
SQL FULL OUTER JOIN возвращает все записи из таблиц table1 и table2.
Пример
Давайте рассмотрим пример, который показывает, как использовать FULL OUTER JOIN в операторе SELECT.
Используя ту же таблицу customers, что и в предыдущем примере:
| customer_id | first_name | last_name | favorite_website | 
|---|---|---|---|
| 4000 | Justin | Bieber | google.com | 
| 5000 | Selena | Gomez | bing.com | 
| 6000 | Mila | Kunis | yahoo.com | 
| 7000 | Tom | Cruise | oracle.com | 
| 8000 | Johnny | Depp | NULL | 
| 9000 | Russell | Crowe | google.com | 
И таблицу orders со следующими данными:
| order_id | customer_id | order_date | 
|---|---|---|
| 1 | 7000 | 2019/06/18 | 
| 2 | 5000 | 2019/06/18 | 
| 3 | 8000 | 2019/06/19 | 
| 4 | 4000 | 2019/06/20 | 
| 5 | NULL | 2019/07/01 | 
 Введите следующий SQL оператор:
SELECT customers.customer_id,
	   orders.order_id,
	   orders.order_date
  FROM customers
  FULL OUTER JOIN orders
    ON customers.customer_id = orders.customer_id
 ORDER BY customers.customer_id;
Будет выбрано 7 записей. Вот результаты, которые вы получите:
| customer_id | order_id | order_date | 
|---|---|---|
| NULL | 5 | 2019/07/01 | 
| 4000 | 4 | 2019/06/20 | 
| 5000 | 2 | 2019/06/18 | 
| 6000 | NULL | NULL | 
| 7000 | 1 | 2019/06/18 | 
| 8000 | 3 | 2019/06/19 | 
| 9000 | NULL | NULL | 
Это пример FULL OUTER JOIN будет возвращать все строки из таблицы orders и все строки из таблицы customers. Всякий раз, когда условие соединения не выполняется, значение NULL будет распространяться на эти поля в наборе результатов. Это означает, что если значение customer_id в таблице customers не существует в таблице orders, то все поля в таблице orders будут отображаться в наборе результатов как NULL Кроме того, если значение customer_id в таблице orders не существует в таблице customers, то все поля в таблице customers будут отображаться в наборе результатов как NULL.
Как видите, строки, где customer_id равен 6000 и 9000, будут включены, но поля order_id и order_date для этих записей содержат значение NULL. Строка, где order_id равен 5, также будет включена, но поле customer_id для этой записи имеет значение NULL.
INNER JOIN (внутреннее соединение)
Запрос с оператором INNER JOIN предназначен для соединения таблиц и вывода результирующей таблицы,
в которой данные полностью пересекаются по условию, указанному после ON.
То же самое делает и просто
JOIN. Таким образом, слово INNER — не обязательное.
Есть база данных портала объявлений — 2. В ней есть таблица
Categories (категории объявлений) и Parts (части, или иначе — рубрики, которые и относятся к категориям).
Например, части Квартиры, Дачи относятся к категории Недвижимость, а части Автомобили, Мотоциклы — к категории
Транспорт.
Если вы хотите выполнить запросы к базе данных из этого урока на MS SQL Server, но эта СУБД
не установлена на вашем компьютере, то ее можно установить, пользуясь инструкцией по этой ссылке.
Скрипт для создания базы данных портала объявлений — 2, её таблиц и заполения таблиц данными —
в файле по этой ссылке.
Таблицы этой базы данных с заполненными данными имеют следующий вид.
Таблица Categories:
| Catnumb | Cat_name | Price | 
| 10 | Стройматериалы | 105,00 | 
| 505 | Недвижимость | 210,00 | 
| 205 | Транспорт | 160,00 | 
| 30 | Мебель | 77,00 | 
| 45 | Техника | 65,00 | 
Таблица Parts:
| Part_ID | Part | Cat | 
| 1 | Квартиры | 505 | 
| 2 | Автомашины | 205 | 
| 3 | Доски | 10 | 
| 4 | Шкафы | 30 | 
| 5 | Книги | 160 | 
Заметим, что в таблице Parts Книги имеют Cat — ссылку на категорию, которой нет в
таблице Categories, а в таблице Categories Техника имеет номер категории Catnumb — значение, ссылки на которое
нет в таблице Parts.
Пример 1. Требуется соединить данные этих двух таблиц так, чтобы в результирующей таблице
были поля Part (Часть), Cat (Категория) и Price (Цена подачи объявления) и чтобы данные полностью
пересекались по условию. Условие — совпадение номера категории (Catnumb) в таблице Categories и ссылки
на категорию в таблице Parts. Для этого пишем следующий запрос:
   SELECT Parts.Part, Categories.Catnumb AS Cat, Categories.Price
      FROM Parts INNER JOIN Categories
	     ON Parts.Cat = Categories.Catnumb
Результатом выполнения запроса будет следующая таблица:
| Part | Cat | Price | 
| Квартиры | 505 | 210,00 | 
| Автомашины | 205 | 160,00 | 
| Доски | 10 | 105,00 | 
| Шкафы | 30 | 77,00 | 
В результирующей таблице нет Книг, так как эта запись ссылается на категорию, которой
нет в таблице Categories, и Техники, так как эта запись имеет внешний ключ в таблице Categories, на
который нет ссылки в таблице Parts.
В ряде случаев при соединениях таблиц составить менее громоздкие запросы
можно с помощью предиката EXISTS и без использования JOIN.



 
							 
							