×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

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

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

1.2.6. Соединение таблиц

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

SELECT * FROM weather JOIN cities ON city = name;

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
(2 rows)

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

  • Нет строки результата для города Хейвард (Hayward). Это потому, что нет соответствующей записи в таблице cities для Хейварда, поэтому соединение игнорирует несовпадающие строки в таблице weather. Мы скоро увидим, как это можно исправить.

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

    SELECT city, temp_lo, temp_hi, prcp, date, location
        FROM weather JOIN cities ON city = name;
    

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

SELECT weather.city, weather.temp_lo, weather.temp_hi,
       weather.prcp, weather.date, cities.location
    FROM weather JOIN cities ON weather.city = cities.name;

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

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

SELECT *
    FROM weather, cities
    WHERE city = name;

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

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

SELECT *
    FROM weather LEFT OUTER JOIN cities ON weather.city = cities.name;

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 Hayward       |      37 |      54 |      | 1994-11-29 |               |
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
(3 rows)

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

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

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

SELECT w1.city, w1.temp_lo AS low, w1.temp_hi AS high,
       w2.city, w2.temp_lo AS low, w2.temp_hi AS high
    FROM weather w1 JOIN weather w2
        ON w1.temp_lo < w2.temp_lo AND w1.temp_hi > w2.temp_hi;

     city      | low | high |     city      | low | high
---------------+-----+------+---------------+-----+------
 San Francisco |  43 |   57 | San Francisco |  46 |   50
 Hayward       |  37 |   54 | San Francisco |  46 |   50
(2 rows)

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

SELECT *
    FROM weather w JOIN cities c ON w.city = c.name;

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



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

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению