1С. Запросы. Левое соединение работает как внутреннее – урезаются данные из левой таблицы.
При попытке соединения в запросе двух таблиц в режиме «Левое соединение» иногда возникает ситуация, когда данные из левой таблицы выбираются не все, как должно быть, а только те, которые есть в правой таблице. То есть, получается «Внутреннее соединение».
Например, мы хотим выбрать все документы «Заказ клиента» за какой-то период и соединить каждый из них со своим значением дополнительного сведения «Вип заказ», которое имеет тип «Булево» и хранится в регистре сведений «Дополнительные сведения».
Нужно помнить, что в указанном регистре сведений находятся не все документы «Заказ клиента», а только те, у которых значение дополнительного сведения «Вип заказ» установлено в «Да».
Итак, пишем запрос:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ЗаказыКлиентов.Ссылка КАК ЗаказКлиента, | ДополнительныеСведения.Значение КАК ЭтоВипЗаказ |ИЗ | Документ.ЗаказКлиента КАК ЗаказыКлиентов | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения | ПО (ЗаказыКлиентов.Ссылка = ДополнительныеСведения.Объект) |ГДЕ | ДополнительныеСведения.Свойство = &СвойствоДопСведения"; Запрос.УстановитьПараметр("СвойствоДопСведения", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вип заказ (Список заказов клиентов)"); Запрос.Выполнить();
В выборке этого запроса мы увидим результат не «Левого соединения», которое мы указали в тексте запроса, а «Внутреннего соединения». В выборке окажутся только те документы «Заказ клиента», которые присутствуют в правой таблице – «ДополнительныеСведения».
Чтобы избежать такую ситуацию, нужно использовать временную таблицу или вложенный запрос.
Решение с использованием временной таблицы:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ДополнительныеСведения.Объект КАК ЗаказКлиента, | ДополнительныеСведения.Значение КАК ЭтоВипЗаказ |ПОМЕСТИТЬ ДополнительныеСведения |ИЗ | РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения |ГДЕ | ДополнительныеСведения.Свойство = &СвойствоДопСведения |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ЗаказыКлиентов.Ссылка КАК ЗаказКлиента, | ДополнительныеСведения.ЭтоВипЗаказ КАК ЭтоВипЗаказ |ИЗ | Документ.ЗаказКлиента КАК ЗаказыКлиентов | ЛЕВОЕ СОЕДИНЕНИЕ ДополнительныеСведения КАК ДополнительныеСведения | ПО ЗаказыКлиентов.Ссылка = ДополнительныеСведения.ЗаказКлиента"; Запрос.УстановитьПараметр("СвойствоДопСведения", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вип заказ (Список заказов клиентов)"); Запрос.Выполнить();
Решение с использованием вложенного запроса:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ЗаказыКлиентов.Ссылка КАК ЗаказКлиента, | ДополнительныеСведения.ЭтоВипЗаказ КАК ЭтоВипЗаказ |ИЗ | Документ.ЗаказКлиента КАК ЗаказыКлиентов | ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ | ДополнительныеСведения.Объект КАК ЗаказКлиента, | ДополнительныеСведения.Значение КАК ЭтоВипЗаказ | ИЗ | РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения | ГДЕ | ДополнительныеСведения.Свойство = &СвойствоДопСведения) КАК ДополнительныеСведения | ПО (ЗаказыКлиентов.Ссылка = ДополнительныеСведения.ЗаказКлиента)"; Запрос.УстановитьПараметр("СвойствоДопСведения", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вип заказ (Список заказов клиентов)"); Запрос.Выполнить();
Оба эти варианты запросов дадут в итоге настоящее «Левое соединение»: в выборку попадут все документы «Заказ клиента» из левой таблицы и значения дополнительного сведения из правой таблицы для тех документов, у которых это сведение задано.
- 1С
- Запросы
- Временные таблицы
Как работает левое соединение 1с
Есть 2 запроса, где условие на выбираемые документы сделано через левое соединение и через условие В. Левое соединение работает в несколько раз быстрее.
Вопрос такой: т.к. «В» более читабельное (особенно когда есть несколько подобных условий) то как реализовать условие В чтобы оно работало оптимально?
МЕДЛЕННЫЙ ЗАПРОС (несколько секунд):
ВЫБРАТЬ
Доверенность.ДокументРасчетов КАК Док
ПОМЕСТИТЬ ДокументыРасчетов
ИЗ
Документ.Доверенность.ДокументыРасчетов КАК Доверенность
ГДЕ
Доверенность.Ссылка = &ДокументСсылка
И ТИПЗНАЧЕНИЯ(Доверенность.ДокументРасчетов) = ТИП(Документ.Реализация)
ВЫБРАТЬ
Товары.Сумма
ИЗ
Документ.Реализация.Товары КАК Товары
ГДЕ
Товары.Ссылка В
(ВЫБРАТЬ
ДокументыРасчетов.Док
ИЗ
ДокументыРасчетов)
БЫСТРЫЙ ЗАПРОС (доли секунды):
ВЫБРАТЬ РАЗЛИЧНЫЕ
Доверенность.ДокументРасчетов КАК Док
ПОМЕСТИТЬ ДокументыРасчетов
ИЗ
Документ.Доверенность.ДокументыРасчетов КАК Доверенность
ГДЕ
Доверенность.Ссылка = &ДокументСсылка
И ТИПЗНАЧЕНИЯ(Доверенность.ДокументРасчетов) = ТИП(Документ.Реализация)
;
ВЫБРАТЬ
Товары.Сумма
ИЗ
ДокументыРасчетов КАК ДокументыРасчетов
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Реализация.Товары КАК Товары
ПО ДокументыРасчетов.Док = Товары.Ссылка
а что будет работать быстрее запрос в цикле (вар1) или вложеный запрос(вар2)?
»
ГДЕ
Товары.Ссылка В
(ВЫБРАТЬ
ДокументыРасчетов.Док
ИЗ
ДокументыРасчетов ГДЕ ТОвары.Ссылка = ДокументыРасчетов.Товары.Ссылка)
«
(0) В первом случае отбираются доверенности. Затем выбираются все реализации и доверенности, и только потом на них накладывается условие.
Во втором случае выбираются доверенности, затем происходит соединение таблиц без всяких условий, т.е. «отбор» идет на уровне соединения таблиц.
Плюс кошернее вместо
ТИПЗНАЧЕНИЯ(Доверенность.ДокументРасчетов) = ТИП(Документ.Реализация)
писать
Доверенность.ДокументРасчетов ССЫЛКА Документ.Реализация
Соединение таблиц в запросах 1С
В предыдущей статье был рассмотрен вопрос чем отличается соединение таблиц от объединения. А сейчас рассмотрим подробнее соединение таблиц.
Напомню, что видов соединений в языке запросов 1С8 может быть несколько, а именно: ЛЕВОЕ СОЕДИНЕНИЕ, ПРАВОЕ СОЕДИНЕНИЕ, ВНУТРЕННЕЕ СОЕДИНЕНИЕ, ПОЛНОЕ СОЕДИНЕНИЕ. Рассмотрим каждое из них подробно.
ЛЕВОЕ СОЕДИНЕНИЕ
В случае левого соединения данные из одной таблицы выбираются полностью, а из таблицы, которая присоединяется справа, выбираются только те записи для которых выполняется одно или несколько условий по которым эти таблицы соединяются. Из этого предложения конечно же мало, что можно понять, поэтому разберем пример.
Есть таблица «Товары»:
| КодТовара | Наименование |
|---|---|
| 001 | Яблоки |
| 002 | Апельсины |
| 003 | Мандарины |
Сформируем эту таблицу в консоли запросов 1С с помощью вот такого запроса:
ВЫБРАТЬ "001" КАК КодТовара, "Яблоки" КАК Наименование ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "Апельсины" ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "003", "Мандарины"
А еще есть таблица «Страны» вот такого вида:
| КодТовара | Страна |
|---|---|
| 001 | Россия |
| 002 | Турция |
| 003 | Марокко |
Также сконструируем ее запросом:
ВЫБРАТЬ "001" КАК КодТовара, "Россия" КАК Страна ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "Турция" ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "003", "Марокко"
А теперь соединим эти две таблицы с помощью левого соединения, чтобы получить одну, в которой будет и код товара, и наименование, и страна. Для этого поместим наши таблицы во временные и в пакетном запросе выполним левое соединение.
Записи будем связывать конечно же по полям КодТовара
ВЫБРАТЬ "001" КАК КодТовара, "Яблоки" КАК Наименование ПОМЕСТИТЬ ВТ_Товар ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "Апельсины" ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "003", "Мандарины" ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ "001" КАК КодТовара, "Россия" КАК Страна ПОМЕСТИТЬ ВТ_Страна ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "Турция" ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "003", "Марокко" ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВТ_Товар.КодТовара, ВТ_Товар.Наименование, ВТ_Страна.Страна ИЗ ВТ_Товар КАК ВТ_Товар ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Страна КАК ВТ_Страна ПО ВТ_Товар.КодТовара = ВТ_Страна.КодТовара
Можете скопировать этот код в консоль запросов и выполнив его получите вот такой результат:
| КодТовара | Наименование | Страна |
|---|---|---|
| 001 | Яблоки | Россия |
| 002 | Апельсины | Турция |
| 003 | Мандарины | Марокко |
Здесь мы рассмотрели идеальную ситуацию, когда каждой записи в левой таблице соответствует одна запись в правой. Давайте немного усложним.
Допустим для нашего товара у нас есть еще цены. Причем они могут меняться в зависимости от даты:
| КодТовара | Дата | Цена |
|---|---|---|
| 001 | 01.01.2016 | 120 |
| 001 | 01.02.2016 | 150 |
| 002 | 01.01.2016 | 200 |
| 004 | 01.01.2016 | 350 |
Здесь мы видим, что для товара с кодом 001 (Яблоки) у нас 2 записи в таблице цен. Для мандаринов цена отсутствует. И кроме того в ценах есть код товара 004, которого нет в таблице с товарами. Давайте выполним левое соединение для товаров и цен с условием связи по полю код и посмотрим, что у нас получится.
ВЫБРАТЬ "001" КАК КодТовара, "Яблоки" КАК Наименование ПОМЕСТИТЬ ВТ_Товар ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "Апельсины" ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "003", "Мандарины" ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ "001" КАК КодТовара, "01.01.2016" КАК Дата, 120 КАК Цена ПОМЕСТИТЬ ВТ_Цена ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "001", "01.02.2016", 150 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "002", "01.01.2016", 200 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ "004", "01.01.2016", 350 ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВТ_Товар.КодТовара, ВТ_Товар.Наименование, ВТ_Цена.Цена, ВТ_Цена.Дата ИЗ ВТ_Товар КАК ВТ_Товар ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Цена КАК ВТ_Цена ПО ВТ_Товар.КодТовара = ВТ_Цена.КодТовара
ПРАВОЕ СОЕДИНЕНИЕ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
В случае внутреннего соединения в итоговую таблицу попадут только те записи как из левой, так и из правой таблицы, для которых выполняется условие соединения. Если в нашем последнем запросе мы заменим строку
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Цена КАК ВТ_Цена
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Цена КАК ВТ_Цена
ПОЛНОЕ СОЕДИНЕНИЕ
В случае полного соединения в итоговую таблицу попадут все записи из обоих таблиц.
В нашем случае при использовании строки соединения
ПОЛНОЕ СОЕДИНЕНИЕ ВТ_Цена КАК ВТ_Цена
Для тех кто только начинает работать с запросами 1С8 советую посмотреть как разные виды соединений отображаются в конструкторе запросов на закладке «Связи».
Как работает левое соединение 1с
Вступайте в мою группу помощник программиста.
В ней мы обсуждаем программирование в 1С.
Оглавление (нажмите, чтобы раскрыть)
- Как сделать внутреннее соединение таблиц
- Как сделать левое внешнее соединение таблиц
- Как сделать правое внешнее соединение таблиц
- Как сделать полное внешнее соединение таблиц
- Как сделать перекрестное соединение таблиц
- Скачать и выполнить эти примеры на компьютере
Соединение в запросах в языке 1С 8.3, 8.2 (в примерах)
С уважением, Владимир Милькин (преподаватель школы 1С программистов и разработчик обновлятора).

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