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

Источник: http://zapros-1c-8.ru/9-yazik-zaprosov-1c-8/15-union

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

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

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

Запрос.Текст =

"

//посчитаем на какую сумму мы отгрузили контрагентам

|ВЫБРАТЬ

| Расход.Контрагент,

| СУММА(Расход.Сумма) КАК Долг

|ИЗ

| Документ.Расход КАК Расход

|

|СГРУППИРОВАТЬ ПО

| Расход.Контрагент

|

|ОБЪЕДИНИТЬ ВСЕ

|

//посчитаем на какую сумму контрагенты

//поставили нам товара

|ВЫБРАТЬ

| Приход.Контрагент,

//сумму берем с отрицательным знаком,

//что при объединении она вычлась из суммы расхода

| СУММА(-Приход.Сумма)

|ИЗ

| Документ.Приход КАК Приход

|

|СГРУППИРОВАТЬ ПО

| Приход.Контрагент";

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

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Расход.Контрагент,

| СУММА(Расход.Сумма) КАК Долг

|ПОМЕСТИТЬ ВТ_ПриходРасход

|ИЗ

| Документ.Расход КАК Расход

|

|СГРУППИРОВАТЬ ПО

| Расход.Контрагент

|

|ОБЪЕДИНИТЬ ВСЕ

|

|ВЫБРАТЬ

| Приход.Контрагент,

| СУММА(-Приход.Сумма)

|ИЗ

| Документ.Приход КАК Приход

|

|СГРУППИРОВАТЬ ПО

| Приход.Контрагент

|;

|

|////////////////////////////////////////////////////////////////////////////////

|ВЫБРАТЬ

| ВТ_ПриходРасход.Контрагент,

| СУММА(ВТ_ПриходРасход.Долг) КАК Долг

|ИЗ

| ВТ_ПриходРасход КАК ВТ_ПриходРасход

|

|СГРУППИРОВАТЬ ПО

| ВТ_ПриходРасход.Контрагент";

Результат:

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

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Расход.Контрагент,

| СУММА(Расход.Сумма) КАК Долг,

| СУММА(Расход.Скидка) КАК Скидка

|ИЗ

| Документ.Расход КАК Расход

|

|СГРУППИРОВАТЬ ПО

| Расход.Контрагент

|

|ОБЪЕДИНИТЬ ВСЕ

|

|ВЫБРАТЬ

| Приход.Контрагент,

| СУММА(-Приход.Сумма),

//добавляем нулевое поле скидка

| 0

|ИЗ

| Документ.Приход КАК Приход

|

|СГРУППИРОВАТЬ ПО

| Приход.Контрагент";

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

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Расход.Контрагент,

| СУММА(Расход.Сумма) КАК Долг,

| СУММА(Расход.Скидка) КАК Скидка

|ИЗ

| Документ.Расход КАК Расход

|

|СГРУППИРОВАТЬ ПО

| Расход.Контрагент

|

|ОБЪЕДИНИТЬ ВСЕ

|

|ВЫБРАТЬ

| Приход.Контрагент,

//меняем местами

| 0,

| СУММА(-Приход.Сумма)

|ИЗ

| Документ.Приход КАК Приход

|

|СГРУППИРОВАТЬ ПО

| Приход.Контрагент";

Получим: