К статьям

Соединения в запросе

7 мин


Описание

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

Секция ИЗ в запросе предоставляет возможность нескольких вариантов использования соединений.

Условимся что у нас есть две вот такие таблицы с данными:
В базе данных хранится таблица Фрукты, в которой мы храним названия фруктов и их количество. И таблица Цвета фруктов, в которой хранится цвет для фруктов, но не для всех. 

Фрукты Цвета фруктов
Название Количество
Яблоко 5
Апельсин 6
Банан 12
Фрукт Цвет
Яблоко Зеленый
Банан Желтый

 

Левое соединение

Один из самых распространенных вариантов соединения Левое соединение. Синтаксис этой конструкции имеет следующий вид:
<Таблица1> Левое Соединение <Таблица2>
   ПО <УсловиеСоединения>
   И|ИЛИ <Еще одно условие соединения>. 
Количество условий соединений не ограничено.

В этом варианте соединения следует запомнить основной правило, к Таблица1 присоединяется Таблица2. Таблица1 при этом остается в исходном виде, а из Таблица2 в результат попадают только те записи, которые соответствуют условию соединения после оператора ПО.

Взяв таблицы Фрукты, ЦветаФруктов и использовав оператор Левое Соединение мы можем добиться следующего результата.

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты
        ЛЕВОЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт 

Результат:

Название Количество Цвет
Яблоко 5 Зеленый
Апельсин 6 NULL
Банан 12 Желтый

Как видим таблица Фрукты осталась в исходном виде, а из таблицы Цвет фруктов  в результат попали только значения, которые есть в таблице Фрукты. Значения тех полей, которые не нашли соответствия в присоединяемой таблице, не присоединились, заполняются значением NULL. 

Так же можно представить это соединение в графическом виде

Правое соединение

Синтаксис этой конструкции имеет следующий вид:
<Таблица1> Правое Соединение <Таблица2>
   ПО <УсловиеСоединения>
   И|ИЛИ <Еще одно условие соединения>.

Этот вариант соединения аналогичен левому соединению, с единственным отличием, здесь Таблица1 будет присоединяться к Таблица2.

Пример запроса:

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты
        ПРАВОЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт 

Результат:

Название Количество Цвет
Яблоко 5 Зеленый
Банан 12 Желтый

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

Так же это соединение можно представить в графическом виде


Следует помнить, что при написании запросов в конструкторе запросов 1С, он автоматически заменяет правое соединение на левое, меняя таблицы местами. Это не влияет на результат, и никак не мешает, следует это просто помнить, чтобы не удивляться почему мы писали правое, а потом оно стало левым)

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

Внутреннее соединение имеет похожий синтаксис:
<Таблица1> Внутреннее Соединение <Таблица2>
   ПО <УсловиеСоединения>
   И|ИЛИ <Еще одно условие соединения>, 
но в результате соединения в результат попадают только записи соотвествующие условию в обеих таблицах. 

Добавим в таблицу цветов фруктов еще одну запись, чтобы увидеть результат более наглядно 

Фрукт Цвет
Яблоко Зеленый
Банан Желтый
Кокос Коричневый
 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт 

Результат:

Название Количество Цвет
Яблоко 5 Зеленый
Банан 12 Желтый

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

Графически это можно изобразить так:

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

Синтаксис полного соединения:
<Таблица1> Полное Соединение <Таблица2>
   ПО <УсловиеСоединения>
   И|ИЛИ <Еще одно условие соединения>.

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

Рассмотрим пример запроса:

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты
        ПОЛНОЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт 

Результат:

Название Количество Цвет
Яблоко 5 Зеленый
Апельсин 6 NULL
Банан 12 Желтый
NULL NULL Коричневый

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

Графически это можно изобразить вот так

Перекрестное соединение (Декартово произведение)

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

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

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты,
    ЦветаФруктов КАК ЦветаФруктов 

Результат будет следующий:

Название Количество Цвет
Яблоко 5 Зеленый
Яблоко 5 Желтый
Апельсин 6 Зеленый
Апельсин 6 Желтый
Банан 12 Зеленый
Банан 12 Желтый

Как видно, мы получили данные из двух таблиц в одном запросе, но соединились они довольно странно. Каждая запись из одной таблицы соединилась с каждой записью из другой таблицы, результат получился не корректный. Математика такого результата крайне проста, если знать как перемножаются матрицы. В самом простом объяснении можно сказать, что если в одной таблице 3 записи и в другой таблице 2 записи, то количество строк в результате будет 3*2 = 6. Пока что ценности в этом немного. Обычно такие соединения используют одновременно с отбором в секции ГДЕ. Мы видим, что в обеих таблицах есть поля с одинаковыми значениями Название и Фрукт. Если мы добавим условие на равенство этих полей, то запрос получится следующим:

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты,
    ЦветаФруктов КАК ЦветаФруктов
ГДЕ
    Фрукты.Название = ЦветаФруктов.Фрукт  

 А результат удовлетворит нашим ожиданиям, цвета фруктов соответствуют фруктам:

Название Количество Цвет
Яблоко 5 Зеленый
Банан 12 Желтый

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

Дополнительные примеры использования

Множественные условия в соединении.

Выведутся все записи из таблицы Фрукты, но из таблицы цветов присоединится только цвет для записи "Яблоко":

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет
ИЗ
    Фрукты КАК Фрукты
        ЛЕВОЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт
            И Фрукты.Название = "Яблоко"

 Результат: 

Название Количество Цвет
Яблоко 5 Зеленый
Апельсин 6 NULL
Банан 12 NULL

Множественные соединения в запросе

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

 ВЫБРАТЬ
    Фрукты.Название,
    Фрукты.Количество,
    ЦветаФруктов.Цвет,
    ЦеныФруктов.Цена
ИЗ
    Фрукты КАК Фрукты
        ЛЕВОЕ СОЕДИНЕНИЕ ЦветаФруктов КАК ЦветаФруктов
        ПО Фрукты.Название = ЦветаФруктов.Фрукт
        ЛЕВОЕ СОЕДИНЕНИЕ ЦеныФруктов КАК ЦеныФруктов
        ПО Фрукты.Название = ЦеныФруктов.Фрукт 

Результат: 

Название Количество Цвет Цена
Яблоко 5 Зеленый 50
Апельсин 6 NULL 60
Банан 12 Желтый 70

 

Задачи на эту тему: