1С объединить

Внимание! Перед вами ознакомительная версия урока, материалы которого могут быть неполными.

Войдите как ученик, чтобы получить доступ к материалам школы

Язык запросов 1С 8.3 для начинающих программистов: объединение

Автор уроков и преподаватель школы: Владимир Милькин

Объединение в запросах

В языке запросов имеется возможность объединять несколько запросов. При этом записи, полученные с помощью каждого из объединяемых запросов, будут собраны в один результат запроса.

Как всегда начнём с примера.

Пусть требуется написать запрос, который возвращает все названия цветов и вкусов в одной таблице.

Цвета мы умеем выбирать так:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета

Вкусы так:

ВЫБРАТЬ Наименование ИЗ Справочник.Вкусы

А вот, чтобы объединить эти два результата в один как раз и потребуется операция объединения:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВЫБРАТЬ Наименование ИЗ Справочник.Вкусы

Обратите внимание на то, что операция объединения вовсе не гарантирует, что элементы будут идти в каком-то определённом порядке. В общем случае они могут следовать друг за другом как угодно, поэтому если важен порядок необходимо как и всегда указывать его явно (через секцию УПОРЯДОЧИТЬ).

Требования к запросам, участвующим в объединении

У объединяемых запросов должно быть одинаковое количество полей. Иначе мы получим такую ошибку:

В объединяемых запросах соответствующие друг другу (по порядку) поля должны иметь одинаковый тип. Но это требование, в отличие от предыдущего, не является обязательным. Если соответствующие друг другу поля имеют разный тип, то поле результата будет иметь СОСТАВНОЙ тип, который разбирался нами на одном из прошлых уроков:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВЫБРАТЬ Калорийность ИЗ Справочник.Еда

Несмотря на то, что поле первого запроса имеет тип СТРОКА, а второго ЧИСЛО, нам удалось объединить их в одну таблицу. Но тип результатирующего поля стал составным и нам придётся учитывать это в дальнейшем. Вы читаете ознакомительную версию урока, полноценные уроки находятся .

Кстати, вы заметили, что поле итоговой таблицы (после объединения) называется Наименование, а не Калорийность? Эта такое правило: поля итоговой таблицы всегда имеют названия совпадающие с именами описанными в первом из объединяемых запросов.

Объединение более двух запросов

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

Напишем объединение трёх запросов:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВЫБРАТЬ Калорийность ИЗ Справочник.Еда ОБЪЕДИНИТЬ ВЫБРАТЬ Код ИЗ Справочник.Вкусы

Повторяющиеся строки

Давайте объединим один и тот же запрос сам с собой:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВЫБРАТЬ Наименование ИЗ Справочник.Цвета

Обратите внимание на то, что мы объединили две одинаковые таблицы цветов, а в результате каждый цвет встречается ровно один раз.

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

Если требуется, чтобы были оставлены в том числе одинаковые строки (дубли), необходимо указать ключевое слово ВСЕ:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Наименование ИЗ Справочник.Цвета

Упорядочивание при объединении

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

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета УПОРЯДОЧИТЬ ПО Наименование ОБЪЕДИНИТЬ ВЫБРАТЬ Наименование ИЗ Справочник.Вкусы

Получим ошибку:

Упорядочивать можно только результат объединения:

ВЫБРАТЬ Наименование ИЗ Справочник.Цвета ОБЪЕДИНИТЬ ВЫБРАТЬ Наименование ИЗ Справочник.Вкусы УПОРЯДОЧИТЬ ПО Наименование УБЫВ

Обратите внимание на то, что секция УПОРЯДОЧИТЬ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.

Подведение итогов при объединении

Пытаться отдельно подводить итоги по запросам, участвующим в объединении, также не имеет смысла. Поэтому при попытке написать:

ВЫБРАТЬ Вкус ИЗ Справочник.Еда ИТОГИ ПО Вкус ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Цвет ИЗ Справочник.Еда

Получим ошибку:

Подводить итоги можно только по результату объединения:

ВЫБРАТЬ Вкус ИЗ Справочник.Еда ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Цвет ИЗ Справочник.Еда ИТОГИ ПО Вкус

Обратите внимание на то, что секция ИТОГИ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.

Рабочий пример

Давайте решим такую задачу. Требуется вывести для каждого элемента справочника Еда закупленное и проданное количество за весь период.

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

Сначала выберем все строки табличной части Еда из всех поступлений:

ВЫБРАТЬ Номенклатура.Наименование КАК Товар, Количество ИЗ Документ.ПоступлениеЕды.Еда

Теперь сгруппируем этот результат по еде с суммированием количества:

ВЫБРАТЬ Номенклатура.Наименование КАК Товар, СУММА(Количество) КАК Приход ИЗ Документ.ПоступлениеЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура

Аналогичным образом получим продажу еды из документов ПродажаЕды:

ВЫБРАТЬ Номенклатура.Наименование, СУММА(Количество) КАК Расход ИЗ Документ.ПродажаЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура

Осталось объединить эти два запроса:

ВЫБРАТЬ Номенклатура.Наименование КАК Товар, СУММА(Количество) КАК Приход, СУММА(0) КАК Расход ИЗ Документ.ПоступлениеЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Номенклатура.Наименование, СУММА(0), СУММА(Количество) ИЗ Документ.ПродажаЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура УПОРЯДОЧИТЬ ПО Номенклатура.Наименование

Обратите внимание на то, как мы дополнили оба запроса ещё одним полем СУММА(0). Мы вынуждены были сделать это, так как оба запроса содержат по два поля, а объединение запросов должно содержать три поля. Вы читаете ознакомительную версию урока, полноценные уроки находятся . Если бы мы не сделали этого, а написали просто:

ВЫБРАТЬ Номенклатура.Наименование КАК Товар, СУММА(Количество) КАК Приход ИЗ Документ.ПоступлениеЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ Номенклатура.Наименование, СУММА(Количество) КАК Расход ИЗ Документ.ПродажаЕды.Еда СГРУППИРОВАТЬ ПО Номенклатура УПОРЯДОЧИТЬ ПО Номенклатура.Наименование

то получили бы совсем другой результат:

Сравните этот и предыдущий запрос и их результаты.

Пройдите тест

Начать тест

Цитата из справки 1С:
«По умолчанию при объединении запросов полностью одинаковые строки в результате запроса, сформированные РАЗНЫМИ запросами, заменяются одной. Если требуется, чтобы были оставлены разные строки, необходимо указать ключевое слово ВСЕ.»
Конструкция ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ объединяет два результата запроса в один.
Пример запроса для вывода всех документов Приход и Расход:
Код 1C v 8.х ВЫБРАТЬ
Расход.Ссылка
ИЗ
Документ.Расход КАК Расход
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Приход.Ссылка
ИЗ
Документ.Приход КАК Приход
Конструкция ОБЪЕДИНИТЬ — соединяет два результата и группирует повторяющие строки,
А конструкция ОБЪЕДИНИТЬ ВСЕ — НЕ группирует автоматически строки результата.
Подробнее:
Порядок следования определяется порядком в списке полей в предложении ВЫБРАТЬ.
Количество полей можно изменить добавлением пустого фиктивного поля:
Код 1C v 8.х ВЫБРАТЬ
Приходная. Контрагент,
Приходная.Сумма,
0 КАК Менеджер
ИЗ
Документ.Приходная КАК Приходная
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Расходная.Контрагент,
Расходная.Сумма,
Расходная.Сотрудник
ИЗ
Документ.Расходная КАК Расходная
До некоторой степени, операции объединения и соединения прямо противоположны: при соединении у источников обязательно должен быть ключ (при объединении наличие ключа абсолютно не имеет значения), при соединении количество полей может быть произвольным (при объединении количество нолей должно совпадать и поля должны следовать в одном и то же порядке), при соединении природа данных в источниках может быть различна (при объединении связываются однотипные данные).
Смысл механизма
При объединении, фактически, выполняются два запроса, а потом их результаты объединяются в один общий. Конструкция ОБЪЕДИНИТЬ ВСЕ оставит в итоговом запросе только неповторяющиеся записи (то есть, результат её действия аналогичен использованию фразы РАЗЛИЧНЫЕ после выполнения объединения).
Назначение псевдонимов, упорядочивание и расчёт итогов выполняются после объединения и действуют на результирующую таблицу.

Бывают ситуации когда в одном запросе необходимо объединить несколько запросов, причем соединения таблиц никак не могут в этом помочь. Проще всего показать на примере.

Допустим в нашей системе факты покупки и продажи товара регистрируются документами Приход и Расход соответственно. Контрагент может являться как покупателем, так и поставщиком. Зачет задолженности может производится поставкой товара:

Чтобы подсчитать общую задолженность контрагента необходимо сложить сумму всех расходов по этому контрагенту и вычесть сумму всех приходов от этого же контрагента, проще всего это сделать с помощью оператора ОБЪЕДИНИТЬ ВСЕ:

Запрос.Текст =
«
//посчитаем на какую сумму мы отгрузили контрагентам
|ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг
|ИЗ
| Документ.Расход КАК Расход
|
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|
|ОБЪЕДИНИТЬ ВСЕ
|
//посчитаем на какую сумму контрагенты
//поставили нам товара
|ВЫБРАТЬ
| Приход.Контрагент,
//сумму берем с отрицательным знаком,
//что при объединении она вычлась из суммы расхода
| СУММА(-Приход.Сумма)
|ИЗ
| Документ.Приход КАК Приход
|
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент»;

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

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

Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг
|ПОМЕСТИТЬ ВТ_ПриходРасход
|ИЗ
| Документ.Расход КАК Расход
|
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Приход.Контрагент,
| СУММА(-Приход.Сумма)
|ИЗ
| Документ.Приход КАК Приход
|
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ПриходРасход.Контрагент,
| СУММА(ВТ_ПриходРасход.Долг) КАК Долг
|ИЗ
| ВТ_ПриходРасход КАК ВТ_ПриходРасход
|
|СГРУППИРОВАТЬ ПО
| ВТ_ПриходРасход.Контрагент»;

Результат:

Требования к объединению запросов

При объединении двух запросов количество полей у них должно быть одинаковым, если в каком либо из запросов не хватает полей, то их надо добавить в виде констант. Обратимся к примеру выше, пусть в документе расход также есть поле скидка, которое уменьшает сумму долга контрагента, но в документе приход нет никаких скидок. Как быть в этом случае? Так:

Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг,
| СУММА(Расход.Скидка) КАК Скидка

|ИЗ
| Документ.Расход КАК Расход
|
|СГРУППИРОВАТЬ ПО
| Расход.Контрагент
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Приход.Контрагент,
| СУММА(-Приход.Сумма),
//добавляем нулевое поле скидка
| 0
|ИЗ
| Документ.Приход КАК Приход
|
|СГРУППИРОВАТЬ ПО
| Приход.Контрагент»;

Осталось вычесть скидку и сгруппировать.

Также важен порядок. Поля будут объединятся именно в том порядке в котором они указаны в секциях ВЫБРАТЬ обоих запросов. Применительно к предыдущему примеру — поменяем местами поля скидка и сумма в выборке приходов:

Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| Расход.Контрагент,
| СУММА(Расход.Сумма) КАК Долг,
| СУММА(Расход.Скидка) КАК Скидка
|ИЗ
| Документ.Расход КАК Расход

Объединение таблиц в запросах 1С

рубрики: Запросы | Дата: 1 февраля, 2016

Рассмотрим объединение таблиц в запросах 1С8. В этом случае итоговая таблица формируется путем размещенеия записей одной или нескольких таблиц под записями исходной таблицы. Объединение таблиц осуществляется с помощью функции ОБЪЕДИНИТЬ языка запросов 1С.
Эта функция используется в двух вариантах: ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ. Различие между ними в том, что при использовании ОБЪЕДИНИТЬ ВСЕ в итоговую таблицу добавляются все записи из таблиц, которые мы объединяем, а при использовании ОБЪЕДИНИТЬ в случае если в таблицах есть идентичные строки, то в итоговой таблице будет только одна строка, т.е. дубли строк в этом случае удаляются.

Продемонстрирую это на примере.
Откроем консоль запросов и создадим небольшой запрос, который создаст нам элементарную таблицу из пары колонок и одной строки:

ВЫБРАТЬ «001» КАК Код, «professia1c.ru» КАК ИмяСайта

В результате выполнения запроса получаем вот такую таблицу

Код ИмяСайта
001 professia1c.ru

А теперь добавим в нашу таблицу еще пару строк

ВЫБРАТЬ «001» КАК Код, «professia1c.ru» КАК ИмяСайта ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ «002», «1c.ru» ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ «001» КАК Код, «professia1c.ru» КАК ИмяСайта

Соответственно результат:

Код ИмяСайта
001 professia1c.ru
002 1c.ru
001 professia1c.ru

Здесь мы видим, что первая и третья строка дублируются.
А теперь заменим функцию ОБЪЕДИНИТЬ ВСЕ на ОБЪЕДИНИТЬ перед третьей строкой:

ВЫБРАТЬ «001» КАК Код, «professia1c.ru» КАК ИмяСайта ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ «002», «1c.ru» ОБЪЕДИНИТЬ ВЫБРАТЬ «001» КАК Код, «professia1c.ru» КАК ИмяСайта

В итоге видим, что дубли строк у нас исчезли

Код ИмяСайта
001 professia1c.ru
002 1c.ru

Теперь откроем последний запрос в конструкторе и перейдем на закладку Объединения/Псевдонимы, где как раз и отражается факт использования функции ОБЪЕДИНИТЬ.

В правой табличной части мы как раз видим три строчки с запросами, которые подлежат объединению, а флажок Без дубликатов отвечает за то будет ли при объединении использоваться функция ОБЪЕДИНИТЬ либо ОБЪЕДИНИТЬ ВСЕ.

Объединение таблиц с использованием конструктора запросов рассматривается в отдельной статье.