Sql

Join postgresql примеры: PostgreSQL оператор Joins — Oracle PL/SQL •MySQL •MariaDB •SQL Server •SQLite

PostgreSQL оператор Joins — Oracle PL/SQL •MySQL •MariaDB •SQL Server •SQLite

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

Описание

PostgreSQL JOINS используется для извлечения данных из нескольких таблиц. PostgreSQL JOIN выполняется всякий раз, когда две или более таблицы объединяются в операторе SQL.
Существуют разные типы соединений PostgreSQL:

  • PostgreSQL INNER JOIN (или иногда называется простым соединением)
  • PostgreSQL LEFT OUTER JOIN (или иногда называется LEFT JOIN
  • PostgreSQL RIGHT OUTER JOIN (или иногда называется RIGHT JOIN
  • PostgreSQL FULL OUTER JOIN (или иногда называется FULL JOIN

Итак, давайте обсудим синтаксис JOIN в PostgreSQL, посмотрим на визуальные иллюстрации JOIN в PostgreSQL и рассмотрим примеры JOIN.

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

Скорее всего, вы уже написали запрос, который использует PostgreSQL INNER JOIN. Это самый распространенный тип соединения. INNER JOIN возвращают все строки из нескольких таблиц, где выполняется условие соединения.

Синтаксис

Синтаксис для INNER JOIN в PostgreSQL:

SELECT columns FROM table1 INNER JOIN table2 ON table1.column = table2.column;

SELECT columns

FROM table1

INNER JOIN table2

ON table1.column = table2.column;

Визуальная Иллюстрация

На этой визуальной диаграмме PostgreSQL INNER JOIN возвращает затененную область:

PostgreSQL INNER JOIN будет возвращать записи, где пересекаются table1 и table2.

Пример

Вот пример INNER JOIN PostgreSQL:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date FROM suppliers INNER JOIN orders ON suppliers.supplier_id = orders.supplier_id;

SELECT suppliers. supplier_id, suppliers.supplier_name, orders.order_date

FROM suppliers

INNER JOIN orders

ON suppliers.supplier_id = orders.supplier_id;

Этот пример PostgreSQL INNER JOIN вернет все строки из таблиц suppliers и orders, где в таблицах suppliers и orders есть соответствующее значение supplier_id.
Давайте посмотрим на некоторые данные, чтобы объяснить, как работают внутренние соединения:
У нас есть таблица suppliers с двумя полями (supplier_id и supplier_name). Она содержит следующие данные:

supplier_idsupplier_name
10000IBM
10001Hewlett Packard
10002Microsoft
10003NVIDIA

У нас есть еще одна таблица под названием orders с тремя полями (order_id, supplier_id и order_date). Она содержит следующие данные:

order_idsupplier_idorder_date
5001251000010. 04.2019
5001261000120.04.2019
5001271000430.04.2019

Если мы запустим оператор PostgreSQL SELECT (который содержит INNER JOIN) ниже:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date FROM suppliers INNER JOIN orders ON suppliers.supplier_id = orders.supplier_id;

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date

FROM suppliers

INNER JOIN orders

ON suppliers.supplier_id = orders.supplier_id;

Наш набор результатов будет выглядеть так:

supplier_idnameorder_date
10000IBM10.04.2019
10001Hewlett Packard20.04.2019

Строки для ‘Microsoft’ и ‘NVIDIA’ из таблицы suppliers будут опущены, поскольку 10002 и 10003 supplier_id не существуют в обеих таблицах. Строка для 500127 (order_id) из таблицы orders будет опущена, так как supplier_id 10004 не существует в таблице suppliers.

Старый синтаксис

В завершение стоит упомянуть, что приведенный выше пример INGER JOIN PostgreSQL можно переписать с использованием более старого неявного синтаксис следующим образом (но мы все же рекомендуем использовать синтаксис c ключевыми словами INNER JOIN):

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date FROM suppliers, orders WHERE suppliers.supplier_id = orders.supplier_id;

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date

FROM suppliers, orders

WHERE suppliers.supplier_id = orders.supplier_id;

LEFT OUTER JOIN

Другой тип соединения называется PostgreSQL LEFT OUTER JOIN. Этот тип соединения возвращает все строки из таблиц с левосторонним соединением, указанным в условии ON, и только те строки из другой таблицы, где объединяемые поля равны (выполняется условие соединения).

Синтаксис

Синтаксис для PostgreSQL LEFT OUTER JOIN:

SELECT columns
FROM table1
LEFT OUTER JOIN table2
ON table1.column = table2.column;

Визуальная Иллюстрация

На этой визуальной диаграмме PostgreSQL LEFT OUTER JOIN возвращает затененную область:

PostgreSQL LEFT OUTER JOIN будет возвращать все записи из table1 и только те записи из table2, которые пересекаются с table1.

Пример

Вот пример PostgreSQL LEFT OUTER JOIN:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers
LEFT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

В этом примере LEFT OUTER JOIN будут возвращены все строки из таблицы employees и только те строки из таблицы orders, где объединенные поля равны.

Если значение supplier_id в таблице employees не существует в таблице orders, все поля в таблице orders будут отображаться как в результирующем наборе.
Рассмотрим некоторые данные, чтобы объяснить, как работают LEFT OUTER JOINS:
У нас есть таблица suppliers с двумя полями (supplier_id и supplier_name). Она содержит следующие данные:

supplier_idsupplier_name
10000IBM
10001Hewlett Packard
10002Microsoft
10003NVIDIA

У нас есть вторая таблица с именем orders с тремя полями (order_id, supplier_id и order_date). Она содержит следующие данные:

order_idsupplier_idorder_date
5001251000010.04.2019
5001261000120.04.2019

Если мы запустим оператор SELECT (который содержит LEFT OUTER JOIN) ниже:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers
LEFT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

Наш набор результатов будет выглядеть так:

supplier_idsupplier_nameorder_date
10000IBM10. 04.2019
10001Hewlett Packard20.04.2019
10002Microsoft
10003NVIDIA

Строки для ‘Microsoft’ и ‘NVIDIA’ будут включены, потому что использовался LEFT OUTER JOIN. Однако вы заметите, что поле order_date для этих записей содержит значение .

RIGHT OUTER JOIN

Другой тип соединения называется PostgreSQL RIGHT OUTER JOIN. Этот тип соединения возвращает все строки из таблицы с правосторонним соединением, указанной в условии ON, и только те строки из другой таблицы, где соединенные поля равны (выполняется условие соединения).

Синтаксис

Синтаксис для PostgreSQL RIGHT OUTER JOIN:

SELECT columns
FROM table1
RIGHT OUTER JOIN table2
ON table1.column = table2.column;

Визуальная Иллюстрация

На этой визуальной диаграмме PostgreSQL RIGHT OUTER JOIN возвращает заштрихованную область:

PostgreSQL RIGHT OUTER JOIN будет возвращать все записи из table2 и только те записи из table1, которые пересекаются с table2.

Пример

Вот пример RIGHT OUTER JOIN для PostgreSQL:

SELECT orders.order_id, orders.order_date, suppliers.supplier_name
FROM suppliers
RIGHT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

В этом примере RIGHT OUTER JOIN будет возвращать все строки из таблицы orders и только те строки из таблицы suppliers, где соединенные поля равны.
Если значение supplier_id в таблице orders не существует в таблице suppliers, все поля таблицы suppliers будут отображаться как в результирующем наборе.
Давайте посмотрим на некоторые данные, чтобы объяснить, как работают RIGHT OUTER JOINS:
У нас есть таблица suppliers с двумя полями (supplier_id и supplier_name). Она содержит следующие данные:

supplier_idsupplier_name
10000Yandex
10001Google

У нас есть вторая таблица с именем orders с тремя полями (order_id, supplier_id и order_date). Она содержит следующие данные:

order_idsupplier_idorder_date
5001251000010.04.2019
5001261000120.04.2019
5001271000230.04.2019

Если мы запустим оператор SELECT (который содержит RIGHT OUTER JOIN) ниже:

SELECT orders.order_id, orders.order_date, suppliers.supplier_name
FROM suppliers
RIGHT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

Наш набор результатов будет выглядеть так:

order_idorder_datesupplier_name
50012510.04.2019Yandex
50012620.04.2019Google
50012730.04.2019

Строка для 500127 (order_id) будет включена, поскольку используется RIGHT OUTER JOIN. Однако вы заметите, что поле supplier_name для этой записи содержит значение.

FULL OUTER JOIN

Другой тип соединения называется PostgreSQL FULL OUTER JOIN. Этот тип соединения возвращает все строки из левой таблицы и правой таблицы с NULL — значениями в месте, где условие соединения не выполняется.

Синтаксис

Синтаксис для PostgreSQL FULL OUTER JOIN:

SELECT columns
FROM table1
FULL OUTER JOIN table2
ON table1.column = table2.column;

Визуальная Иллюстрация

На этой визуальной диаграмме PostgreSQL FULL OUTER JOIN возвращает затененную область:

PostgreSQL FULL OUTER JOIN будет возвращать все записи из table1 и table2.

Пример

Рассмотрим пример FULL OUTER JOIN в PostgreSQL :

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers
FULL OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

Этот пример FULL OUTER JOIN будет возвращать все строки из таблицы suppliers и все строки из таблицы orders и всякий раз, когда условие соединения не выполняется, то поля в результирующем наборе будут принимать значения .


Если значение supplier_id в таблице suppliers не существует в таблице orders, все поля в таблице orders будут отображаться как в результирующем наборе. Если значение supplier_id в таблице orders не существует в таблице suppliers, все поля в таблице suppliers будут отображаться как в результирующем наборе.

Давайте посмотрим на некоторые данные, чтобы объяснить, как работают FULL OUTER JOINS:
У нас есть таблица suppliers с двумя полями (supplier_id и supplier_name). Она содержит следующие данные:

supplier_idsupplier_name
10000IBM
10001Hewlett Packard
10002Microsoft
10003NVIDIA

У нас есть вторая таблица с именем orders с тремя полями (order_id, supplier_id и order_date). Она содержит следующие данные:

order_idsupplier_idorder_date
5001251000010. 04.2019
5001261000120.04.2019
5001271000430.04.2019

Если мы запустим SQL запрос (который содержит FULL OUTER JOIN) ниже:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers
FULL OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

Наш набор результатов будет выглядеть так:

supplier_idsupplier_nameorder_date
10000IBM10.04.2019
10001Hewlett Packard20.04.2019
10002Microsoft
10003NVIDIA
30.04.2019

Строки для ‘Microsoft’ и ‘NVIDIA’ будут включены, поскольку использовался FULL OUTER JOIN. Однако вы заметите, что поле order_date для этих записей содержит значение.
Строка для supplier_id 10004 также будет включена, поскольку используется FULL OUTER JOIN. Тем не менее, вы заметите, что поля supplier_id и supplier_name для этих записей содержат значение.

вредные JOIN и OR / Хабр

Бойтесь операций, buffers приносящих…
На примере небольшого запроса рассмотрим некоторые универсальные подходы к оптимизации запросов на PostgreSQL. Пользоваться ими или нет — выбирать вам, но знать о них стоит.

В каких-то последующих версиях PG ситуация может измениться с «поумнением» планировщика, но для 9.4/9.6 она выглядит примерно одинаково, как примеры тут.

Возьму вполне реальный запрос:

SELECT
  TRUE
FROM
  "Документ" d
INNER JOIN
  "ДокументРасширение" doc_ex
    USING("@Документ")
INNER JOIN
  "ТипДокумента" t_doc ON
    t_doc."@ТипДокумента" = d."ТипДокумента"
WHERE
  (d."Лицо3" = 19091 or d."Сотрудник" = 19091) AND
  d."$Черновик" IS NULL AND
  d."Удален" IS NOT TRUE AND
  doc_ex. "Состояние"[1] IS TRUE AND
  t_doc."ТипДокумента" = 'ПланРабот'
LIMIT 1;

про имена таблиц и полей

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

Посмотрим на получившийся план:

[посмотреть на explain.tensor.ru]

144ms и почти 53K buffers — то есть больше 400MB данных! И нам повезет, если все они окажутся в кэше к моменту нашего запроса, иначе он станет в разы дольше при вычитывании с диска.

Алгоритм важнее всего!

Чтобы как-то оптимизировать любой запрос, надо сначала понять, что же он вообще должен делать.
Оставим пока за рамками этой статьи разработку самой структуры БД, и договоримся, что мы можем относительно «дешево» переписать запрос и/или накатить на базу какие-то нужные нам индексы.

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

JOIN + LIMIT 1

Достаточно часто разработчику проще написать запрос, где сначала делается соединение большого количества таблиц, а потом из всего этого множества остается одна-единственная запись. Но проще для разработчика — не значит эффективнее для БД.
В нашем случае таблиц было всего 3 — а какой эффект…

Давайте для начала избавимся от соединения с таблицей «ТипДокумента», а заодно подскажем базе, что у запись типа у нас уникальна (мы-то это знаем, а вот планировщик пока не догадывается):

WITH T AS (
  SELECT
    "@ТипДокумента"
  FROM
    "ТипДокумента"
  WHERE
    "ТипДокумента" = 'ПланРабот'
  LIMIT 1
)
...
WHERE
  d."ТипДокумента" = (TABLE T)
...

Да, если таблица/CTE состоит из единственного поля единственной же записи, то в PG можно писать даже так, вместо

d. "ТипДокумента" = (SELECT "@ТипДокумента" FROM T LIMIT 1)

«Ленивые» вычисления в запросах PostgreSQL

BitmapOr vs UNION

В некоторых случаях Bitmap Heap Scan будет стоить нам очень дорого — например, в нашей ситуации, когда достаточно много записей подпадает под требуемое условие. Получили мы его из-за OR-условия, превратившегося в BitmapOr-операцию в плане.
Вернемся к исходной задаче — надо найти запись, соответствующую

любому

из условий — то есть незачем искать все 59K записей по обоим условиям. Есть способ отработать одно условие, а

ко второму перейти только когда по первому ничего не нашлось

. Нам поможет такая конструкция:

(
  SELECT
    ...
  LIMIT 1
)
UNION ALL
(
  SELECT
    ...
  LIMIT 1
)
LIMIT 1

«Внешний» LIMIT 1 гарантирует, что поиск завершится при нахождении первой же записи. И если она найдется уже в первом блоке, выполнение второго осуществляться не будет (never executed в плане).

«Прячем под CASE» сложные условия

В исходном запросе есть крайне неудобный момент — проверка состояния по связанной таблице «ДокументРасширение». Независимо от истинности остальных условий в выражении (например, d.«Удален» IS NOT TRUE), это соединение выполняется всегда и «стоит ресурсов». Больше или меньше их будет потрачено — зависит от объема этой таблицы.
Но можно модифицировать запрос так, чтобы поиск связанной записи происходил бы только когда это действительно необходимо:

SELECT
  ...
FROM
  "Документ" d
WHERE
  ... /*index cond*/ AND
  CASE
    WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
      SELECT
        "Состояние"[1] IS TRUE
      FROM
        "ДокументРасширение"
      WHERE
        "@Документ" = d."@Документ"
    )
  END

Раз из связываемой таблицы нам

не нужно для результата ни одно из полей

, то мы имеем возможность превратить JOIN в условие по подзапросу.
Оставим индексируемые поля «за скобками» CASE, простые условия от записи вносим в WHEN-блок — и теперь «тяжелый» запрос выполняется только при переходе в THEN.

Моя фамилия «Итого»

Собираем результирующий запрос со всеми описанными выше механиками:

WITH T AS (
  SELECT
    "@ТипДокумента"
  FROM
    "ТипДокумента"
  WHERE
    "ТипДокумента" = 'ПланРабот'
)
  (
    SELECT
      TRUE
    FROM
      "Документ" d
    WHERE
      ("Лицо3", "ТипДокумента") = (19091, (TABLE T)) AND
      CASE
        WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
          SELECT
            "Состояние"[1] IS TRUE
          FROM
            "ДокументРасширение"
          WHERE
            "@Документ" = d."@Документ"
        )
      END
    LIMIT 1
  )
UNION ALL
  (
    SELECT
      TRUE
    FROM
      "Документ" d
    WHERE
      ("ТипДокумента", "Сотрудник") = ((TABLE T), 19091) AND
      CASE
        WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
          SELECT
            "Состояние"[1] IS TRUE
          FROM
            "ДокументРасширение"
          WHERE
            "@Документ" = d. "@Документ"
        )
      END
    LIMIT 1
  )
LIMIT 1;

Подгоняем [под] индексы

Наметанный глаз заметил, что индексируемые условия в подблоках UNION чуть разнятся — это потому, что у нас уже есть подходящие индексы на таблице. А если бы их не было — то стоило бы создать: Документ(Лицо3, ТипДокумента) и Документ(ТипДокумента, Сотрудник).

о порядке полей в ROW-условиях

С точки зрения планировщика, конечно, можно написать и (A, B) = (constA, constB), и (B, A) = (constB, constA). Но при записи в порядке следования полей в индексе, такой запрос просто удобнее потом отлаживать.

Что в плане?

[посмотреть на explain.tensor.ru]

К сожалению, нам не повезло, и в первом UNION-блоке ничего не нашлось, поэтому второй все-таки пошел на выполнение. Но даже при этом — всего 0.037ms и 11 buffers!
Мы ускорили запрос и сократили «прокачку» данных в памяти в несколько тысяч раз, воспользовавшись достаточно простыми методиками — неплохой результат при небольшой копипасте. 🙂

PostgreSQL: Документация: 15: 2.6. Соединения между таблицами

До сих пор наши запросы обращались только к одной таблице за раз. Запросы могут обращаться к нескольким таблицам одновременно или обращаться к одной и той же таблице таким образом, что несколько строк таблицы обрабатываются одновременно. Запросы, которые одновременно обращаются к нескольким таблицам (или к нескольким экземплярам одной и той же таблицы), называются запросами join . Они объединяют строки из одной таблицы со строками из второй таблицы с выражением, указывающим, какие строки должны быть объединены в пары. Например, чтобы вернуть все записи о погоде вместе с местоположением соответствующего города, база данных должна сравнить город столбец каждой строки таблицы погода со столбцом имя всех строк в таблице городов и выберите пары строк, в которых эти значения совпадают. [4] Это можно сделать с помощью следующего запроса:

ВЫБЕРИТЕ * ИЗ ПОГОДЫ ПРИСОЕДИНЯЙТЕСЬ к городам ON city = name;
 
     город | temp_lo | temp_hi | пркп | дата | имя | расположение
---------------+---------+----------+------+------- -----+---------------+-----------
 Сан-Франциско | 46 | 50 | 0,25 | 1994-11-27 | Сан-Франциско | (-194,53)
 Сан-Франциско | 43 | 57 | 0 | 1994-11-29 | Сан-Франциско | (-194,53)
(2 ряда)
 

Обратите внимание на две особенности результирующего набора:

  • Нет строки результатов для города Хейворд. Это связано с тем, что в таблице городов для Хейворда нет соответствующей записи, поэтому объединение игнорирует несопоставленные строки в таблице Weather . Вскоре мы увидим, как это можно исправить.

  • Есть две колонки, содержащие название города. Это правильно, потому что списки столбцов из таблиц Weather и city объединены. Однако на практике это нежелательно, поэтому вы, вероятно, захотите указать выходные столбцы явно, а не использовать * :

    .
    ВЫБЕРИТЕ город, temp_lo, temp_hi, prcp, дату, местоположение
        ОТ ПОГОДЫ ПРИСОЕДИНЯЙТЕСЬ к городам ПО city = name;
     

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

ВЫБЕРИТЕ погода. город, погода.temp_lo, погода.temp_hi,
       погода.prcp, погода.дата, города.местоположение
    ИЗ ПОГОДЫ ПРИСОЕДИНЯЙТЕСЬ к городам ПО Weather.city = city.name;
 

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

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

ВЫБРАТЬ *
    ОТ погоды, города
    ГДЕ город = имя;
 

Этот синтаксис предшествует синтаксису JOIN / ON , который был введен в SQL-92. Таблицы просто перечислены в предложении FROM , а выражение сравнения добавлено в предложение WHERE . Результаты этого старого неявного синтаксиса и более нового явного синтаксиса JOIN / ON идентичны. Но для читателя запроса явный синтаксис облегчает понимание его смысла: условие соединения вводится своим собственным ключевым словом, тогда как ранее условие было смешано с 9Пункт 0005 WHERE вместе с другими условиями.

Теперь мы выясним, как вернуть записи Хейворда. Мы хотим, чтобы запрос сканировал таблицу Weather и для каждой строки находил соответствующие городов строк. Если подходящая строка не найдена, мы хотим, чтобы некоторые «пустые значения» были заменены на столбцы таблицы городов . Такой запрос называется внешним соединением . (Соединения, которые мы видели до сих пор, это внутренних соединения .) Команда выглядит так:

ВЫБРАТЬ *
    ОТ погоды ЛЕВЫЙ ВНЕШНИЙ СОЕДИНЯЙТЕ города НА Weather.city = city.name;
 
     город | temp_lo | temp_hi | пркп | дата | имя | расположение
---------------+---------+----------+------+------- -----+---------------+-----------
 Хейворд | 37 | 54 | | 1994-11-29 | |
 Сан-Франциско | 46 | 50 | 0,25 | 1994-11-27 | Сан-Франциско | (-194,53)
 Сан-Франциско | 43 | 57 | 0 | 1994-11-29 | Сан-Франциско | (-194,53)
(3 ряда)
 

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

Упражнение: Существуют также правые внешние соединения и полные внешние соединения. Попробуйте узнать, что они делают.

Мы также можем объединить таблицу против себя. Это называется самосоединением . В качестве примера предположим, что мы хотим найти все записи о погоде, которые находятся в температурном диапазоне других записей о погоде. Поэтому нам нужно сравнить столбцы temp_lo и temp_hi каждой строки Weather со столбцами temp_lo и temp_hi всех остальных 9.0005 погода строк. Мы можем сделать это с помощью следующего запроса:

ВЫБЕРИТЕ w1.city, w1.temp_lo как низкий, w1.temp_hi как высокий,
       w2.city, w2.temp_lo низкий уровень AS, w2.temp_hi высокий уровень AS
    ОТ погоды w1 ПРИСОЕДИНЯЙТЕСЬ к погоде w2
        ON w1. temp_lo < w2.temp_lo И w1.temp_hi > w2.temp_hi;
 
     город | низкий | высокий | город | низкий | высокая
---------------+-----+------+---------------+----- +------
 Сан-Франциско | 43 | 57 | Сан-Франциско | 46 | 50
 Хейворд | 37 | 54 | Сан-Франциско | 46 | 50
(2 ряда)
 

Здесь мы переименовали таблицу погоды как w1 и w2 , чтобы можно было различать левую и правую стороны соединения. Вы также можете использовать эти виды псевдонимов в других запросах, чтобы сэкономить время на вводе, например:

.
ВЫБРАТЬ *
    ОТ погоды w ПРИСОЕДИНЯЙТЕ города c ПО w.city = c.name;
 

Вы будете часто сталкиваться с этим стилем сокращения.



[4] Это только концептуальная модель. Соединение обычно выполняется более эффективно, чем реальное сравнение каждой возможной пары строк, но это незаметно для пользователя.

PostgreSQL: соединения


В этом руководстве по PostgreSQL объясняется, как использовать PostgreSQL JOINS (внутреннее и внешнее) с синтаксисом, наглядными иллюстрациями и примерами.

Описание

СОЕДИНЕНИЯ PostgreSQL используются для извлечения данных из нескольких таблиц. PostgreSQL JOIN выполняется всякий раз, когда две или более таблиц объединяются в операторе SQL.

Существуют различные типы соединений PostgreSQL:

  • ВНУТРЕННЕЕ СОЕДИНЕНИЕ PostgreSQL (иногда называемое простым соединением)
  • PostgreSQL LEFT OUTER JOIN (или иногда называется LEFT JOIN)
  • PostgreSQL ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ (или иногда называемое ПРАВЫМ СОЕДИНЕНИЕМ)
  • PostgreSQL ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ (или иногда называемое ПОЛНОЕ СОЕДИНЕНИЕ)

Итак, давайте обсудим синтаксис JOIN в PostgreSQL, посмотрим на визуальные иллюстрации JOIN в PostgreSQL и рассмотрим примеры JOIN.

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

Скорее всего, вы уже написали оператор, использующий INNER JOIN в PostgreSQL. Это наиболее распространенный тип соединения. ВНУТРЕННИЕ СОЕДИНЕНИЯ PostgreSQL возвращают все строки из нескольких таблиц, в которых выполняется условие соединения.

Синтаксис

Синтаксис INNER JOIN в PostgreSQL:

 SELECT столбцы
ИЗ таблицы1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ таблица2
ON таблица1.столбец = таблица2.столбец; 

Визуальная иллюстрация

На этой визуальной диаграмме ВНУТРЕННЕЕ СОЕДИНЕНИЕ PostgreSQL возвращает заштрихованную область:

ВНУТРЕННЕЕ СОЕДИНЕНИЕ PostgreSQL возвращает записи, где table1 и table2 пересекаются.

Пример

Вот пример ВНУТРЕННЕГО СОЕДИНЕНИЯ PostgreSQL:

 ВЫБЕРИТЕ Suppliers.supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков
ВНУТРЕННЕЕ СОЕДИНЕНИЕ заказы
ПО Suppliers.supplier_id = orders.supplier_id; 

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

Давайте посмотрим на некоторые данные, чтобы объяснить, как работают ВНУТРЕННИЕ СОЕДИНЕНИЯ:

У нас есть таблица с именем поставщиков с двумя полями (supplier_id и supplier_name). Он содержит следующие данные:

идентификатор_поставщика имя_поставщика
10000 ИБМ
10001 Хьюлетт Паккард
10002 Майкрософт
10003 NVIDIA

У нас есть другая таблица с именем заказы с тремя полями (order_id, supplier_id и order_date). Он содержит следующие данные:

идентификатор_заказа идентификатор_поставщика дата_заказа
500125 10000 12.05.2013
500126 10001 13.05.2013
500127 10004 14.05.2013

Если мы запустим инструкцию PostgreSQL SELECT (содержащую INNER JOIN) ниже:

 ВЫБЕРИТЕ Suppliers. supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков
ВНУТРЕННЕЕ СОЕДИНЕНИЕ заказы
ПО Suppliers.supplier_id = orders.supplier_id; 

Наш результирующий набор будет выглядеть следующим образом:

supplier_id имя дата_заказа
10000 ИБМ 12.05.2013
10001 Хьюлетт Паккард 13.05.2013

Строки для Microsoft и NVIDIA из таблицы поставщиков будут опущены, поскольку идентификаторы Supplier_id 10002 и 10003 не существуют в обеих таблицах. Строка для 500127 (order_id) из таблицы заказов будет опущена, так как supplier_id 10004 не существует в таблице поставщиков.

Старый синтаксис

В заключение стоит упомянуть, что приведенный выше пример PostgreSQL INNER JOIN можно переписать с использованием старого неявного синтаксиса следующим образом (но мы по-прежнему рекомендуем использовать синтаксис ключевого слова INNER JOIN):

 ВЫБЕРИТЕ Suppliers. supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков, заказы
ГДЕ Suppliers.supplier_id = orders.supplier_id; 

ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ

Другой тип соединения называется ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ PostgreSQL. Этот тип соединения возвращает все строки из ЛЕВОЙ таблицы, указанной в условии ON, и только те строки из другой таблицы, в которых соединяемые поля равны (соблюдено условие соединения).

Синтаксис

Синтаксис LEFT OUTER JOIN в PostgreSQL:

 ВЫБЕРИТЕ столбцы
ИЗ таблицы1
ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ table2
ON таблица1.столбец = таблица2.столбец; 

Визуальная иллюстрация

На этой визуальной диаграмме LEFT OUTER JOIN в PostgreSQL возвращает заштрихованную область:

PostgreSQL LEFT OUTER JOIN возвращает все записи из таблицы table1 и только те записи из таблицы table2 , которые пересекаются с таблица1 .

Пример

Вот пример ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ PostgreSQL:

 ВЫБЕРИТЕ Suppliers. supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков
LEFT OUTER JOIN заказы
ПО Suppliers.supplier_id = orders.supplier_id; 

Этот пример LEFT OUTER JOIN вернет все строки из таблицы поставщиков и только те строки из таблицы заказов, в которых объединенные поля равны.

Если значение supplier_id в таблице поставщиков не существует в таблице заказов, все поля в таблице заказов будут отображаться как > в результирующем наборе.

Давайте посмотрим на некоторые данные, чтобы объяснить, как работают ЛЕВЫЕ ВНЕШНИЕ СОЕДИНЕНИЯ:

У нас есть таблица с именем поставщиков с двумя полями (supplier_id и supplier_name). Он содержит следующие данные:

supplier_id имя_поставщика
10000 ИБМ
10001 Хьюлетт Паккард
10002 Майкрософт
10003 NVIDIA

У нас есть вторая таблица с именем orders с тремя полями (order_id, supplier_id и order_date). Он содержит следующие данные:

order_id идентификатор_поставщика дата_заказа
500125 10000 12.05.2013
500126 10001 13.05.2013

Если мы запустим оператор SELECT (который содержит LEFT OUTER JOIN) ниже:

 SELECT Suppliers.supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков
LEFT OUTER JOIN заказы
ПО Suppliers.supplier_id = orders.supplier_id; 

Наш результирующий набор будет выглядеть следующим образом:

supplier_id имя_поставщика дата_заказа
10000 ИБМ 12.05.2013
10001 Хьюлетт Паккард 13.05.2013
10002 Майкрософт <ноль>
10003 NVIDIA <ноль>

Строки для Microsoft и NVIDIA будет включено, потому что использовалось ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ. Однако вы заметите, что поле order_date для этих записей содержит значение .

RIGHT OUTER JOIN

Другой тип соединения называется PostgreSQL RIGHT OUTER JOIN. Этот тип соединения возвращает все строки из ПРАВОЙ таблицы, указанной в условии ON, и только те строки из другой таблицы, где соединяемые поля равны (соблюдено условие соединения).

Синтаксис

Синтаксис для PostgreSQL RIGHT OUTER JOIN:

 ВЫБЕРИТЕ столбцы
ИЗ таблицы1
ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ table2
ON таблица1.столбец = таблица2.столбец; 

Визуальная иллюстрация

На этой визуальной диаграмме ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ PostgreSQL возвращает заштрихованную область:

ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ PostgreSQL возвращает все записи из table2 и только те записи из table1 , которые пересекаются с таблица2 .

Пример

Вот пример ПРАВОГО ВНЕШНЕГО СОЕДИНЕНИЯ PostgreSQL:

 ВЫБЕРИТЕ orders. order_id, orders.order_date, Suppliers.supplier_name
ОТ поставщиков
Заказы RIGHT OUTER JOIN
ПО Suppliers.supplier_id = orders.supplier_id; 

Этот пример RIGHT OUTER JOIN вернет все строки из таблицы заказов и только те строки из таблицы поставщиков, в которых объединенные поля равны.

Если значение supplier_id в таблице заказов не существует в таблице поставщиков, все поля в таблице поставщиков будут отображаться как > в наборе результатов.

Давайте посмотрим на некоторые данные, чтобы объяснить, как работают RIGHT OUTER JOINS:

У нас есть таблица с именем Suppliers с двумя полями (supplier_id и supplier_name). Он содержит следующие данные:

supplier_id имя_поставщика
10000 Яблоко
10001 Гугл

У нас есть вторая таблица с именем заказа с тремя полями (order_id, supplier_id и order_date). Он содержит следующие данные:

order_id идентификатор_поставщика дата_заказа
500125 10000 12.08.2013
500126 10001 13.08.2013
500127 10002 14.08.2013

Если мы запустим оператор SELECT (который содержит ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ) ниже:

 SELECT orders.order_id, orders.order_date, Suppliers.supplier_name
ОТ поставщиков
Заказы RIGHT OUTER JOIN
ПО Suppliers.supplier_id = orders.supplier_id; 

Наш результирующий набор будет выглядеть так:

order_id дата_заказа имя_поставщика
500125 12.08.2013 Яблоко
500126 13. 08.2013 Гугл
500127 14.08.2013 <ноль>

Строка для 500127 (order_id) будет включена, поскольку использовалось ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ. Однако вы заметите, что поле supplier_name для этой записи содержит значение .

FULL OUTER JOIN

Другой тип соединения называется FULL OUTER JOIN в PostgreSQL. Этот тип соединения возвращает все строки из таблицы LEFT-hand и RIGHT-hand таблицы с нулевыми значениями в местах, где условие соединения не выполняется.

Синтаксис

Синтаксис FULL OUTER JOIN в PostgreSQL:

 SELECT columns
ИЗ таблицы1
ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ table2
ON таблица1.столбец = таблица2.столбец; 

Визуальная иллюстрация

На этой визуальной диаграмме FULL OUTER JOIN PostgreSQL возвращает заштрихованную область:

ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ PostgreSQL вернет все записи из таблиц table1 и table2 .

Пример

Вот пример ПОЛНОГО ВНЕШНЕГО СОЕДИНЕНИЯ PostgreSQL:

 ВЫБОР
ОТ поставщиков
ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
ПО Suppliers.supplier_id = orders.supplier_id; 

В этом примере FULL OUTER JOIN будут возвращены все строки из таблицы поставщиков и все строки из таблицы заказов, и всякий раз, когда условие соединения не выполняется, будут расширены на эти поля в результирующем наборе.

Если значение supplier_id в таблице поставщиков не существует в таблице заказов, все поля в таблице заказов будут отображаться как > в наборе результатов. Если значение supplier_id в таблице заказов не существует в таблице поставщиков, все поля в таблице поставщиков будут отображаться как в результирующем наборе.

Давайте посмотрим на некоторые данные, чтобы объяснить, как работают ПОЛНЫЕ ВНЕШНИЕ СОЕДИНЕНИЯ:

У нас есть таблица с именем поставщиков с двумя полями (supplier_id и supplier_name). Он содержит следующие данные:

идентификатор_поставщика имя_поставщика
10000 ИБМ
10001 Хьюлетт Паккард
10002 Майкрософт
10003 NVIDIA

У нас есть вторая таблица с именем orders с тремя полями (order_id, supplier_id и order_date). Он содержит следующие данные:

идентификатор_заказа идентификатор_поставщика дата_заказа
500125 10000 12.08.2013
500126 10001 13.08.2013
500127 10004 14.08.2013

Если мы запустим оператор SQL (который содержит ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ) ниже:

 ВЫБЕРИТЕ Suppliers.supplier_id, Suppliers.supplier_name, orders.order_date
ОТ поставщиков
ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
ПО Suppliers.supplier_id = orders.supplier_id; 

Наш результирующий набор будет выглядеть следующим образом:

supplier_id имя_поставщика дата_заказа
10000 ИБМ 12.08.

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

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