Как в запросе 1С получить данные по двум организациям при выборе одной?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Бухгалтерский учет
← На главную

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

Проанализируем ситуацию: в базе несколько юридических лиц. Нужно получить остатки по бухгалтерскому счету. Если выбрана "Организация А", то запрос должен вернуть данные по "Организации А" и "Организации Б". Если же выбрана любая другая организация, например "Организация В", то результат должен содержать данные только по "Организации В".

Существует несколько способов решить эту задачу. Рассмотрим их от самого простого к наиболее гибкому и масштабируемому.

Решение 1: Использование сложного логического условия в секции "ГДЕ"

Самый прямой способ — это составить в секции ГДЕ запроса сложное условие с использованием логических операторов И и ИЛИ. Этот метод позволяет описать всю логику отбора в одном месте.

Принцип работы:

Запрос будет выбирать данные, если выполняется одно из двух условий:

  1. Организация в записи регистра равна той, что выбрал пользователь.
  2. ИЛИ выбранная пользователем организация является "основной", а организация в записи регистра — "дополнительной".

Для реализации этого в запрос потребуется передать три параметра:

Посмотрим на пример запроса к регистру бухгалтерии:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.СуммаОстаток,
    ХозрасчетныйОстатки.Организация
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, , ,) КАК ХозрасчетныйОстатки
ГДЕ
    // Условие 1: всегда выбираем данные по выбранной организации
    (ХозрасчетныйОстатки.Организация = &ВыбраннаяОрганизация)
    ИЛИ
    // Условие 2: если выбранная организация - "основная", то добавляем "дополнительную"
    (&ВыбраннаяОрганизация = &ОсновнаяОрганизация И ХозрасчетныйОстатки.Организация = &ДополнительнаяОрганизация)

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

Решение 2: Объединение запросов

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

Принцип работы:

  1. Первый подзапрос всегда выбирает данные по организации, которую указал пользователь (&ВыбраннаяОрганизация).
  2. Второй подзапрос пытается выбрать данные по "дополнительной" организации. Однако он содержит условие ГДЕ &ВыбраннаяОрганизация = &ОсновнаяОрганизация. Это означает, что второй подзапрос вернет данные только в том случае, если пользователь выбрал именно "основную" организацию. В противном случае он вернет пустой результат.

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

Пример реализации:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.СуммаОстаток,
    ХозрасчетныйОстатки.Организация
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, Организация = &ВыбраннаяОрганизация, ,) КАК ХозрасчетныйОстатки

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

ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.СуммаОстаток,
    ХозрасчетныйОстатки.Организация
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, Организация = &ДополнительнаяОрганизация, ,) КАК ХозрасчетныйОстатки
ГДЕ
    // Этот подзапрос сработает только если выбрана "основная" организация
    &ВыбраннаяОрганизация = &ОсновнаяОрганизация

Этот метод хорошо разделяет логику и делает запрос более структурированным, особенно если условия для второго подзапроса становятся сложнее.

Решение 3: Пакетный запрос с использованием временной таблицы

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

Принцип работы:

  1. Первый запрос пакета: Создаем временную таблицу ВТ_НужныеОрганизации. Сначала помещаем в нее организацию, выбранную пользователем. Затем, с помощью ОБЪЕДИНИТЬ ВСЕ, добавляем в эту же таблицу "дополнительную" организацию, но только если выполняется условие (выбрана "основная" организация).
  2. Второй запрос пакета: Это основной запрос, который извлекает нужные данные из регистра бухгалтерии. В качестве фильтра по организации он использует конструкцию ГДЕ Организация В (...), где вложенный запрос выбирает все организации из нашей ранее созданной временной таблицы.

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

Пример пакетного запроса (запросы разделяются точкой с запятой):


// Первый запрос пакета: создание и заполнение временной таблицы со списком нужных организаций
ВЫБРАТЬ
    &ВыбраннаяОрганизация КАК Организация
ПОМЕСТИТЬ ВТ_НужныеОрганизации

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

ВЫБРАТЬ
    &ДополнительнаяОрганизация
ГДЕ
    &ВыбраннаяОрганизация = &ОсновнаяОрганизация
;

////////////////////////////////////////////////////////////////////////////////
// Второй запрос пакета: основной запрос к данным
ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.СуммаОстаток,
    ХозрасчетныйОстатки.Организация
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(
            &Дата,
            ,
            Организация В (ВЫБРАТЬ Организация ИЗ ВТ_НужныеОрганизации),
            ) КАК ХозрасчетныйОстатки

Преимущества этого метода:

Альтернативный подход: подготовка параметров в коде 1С

Хотя исходная задача требовала решения "только запросом", стоит упомянуть и классический подход, который часто является самым простым в реализации. Суть в том, чтобы подготовить список нужных организаций в коде 1С, а затем передать его в запрос как один параметр.

Принцип работы:

Перед выполнением запроса в коде модуля создается объект СписокЗначений. В него добавляется выбранная пользователем организация, а затем, после проверки условия, добавляется и вторая. Этот список передается в запрос, который использует простое условие ГДЕ Организация В (&СписокОрганизаций).

Пример кода на встроенном языке 1С:


// Предположим, что объект.ВыбраннаяОрганизация - это выбор пользователя
// А ПерваяОрганизация и СестраПервойОрганизации - заранее полученные ссылки
СписокОрганизаций = Новый СписокЗначений;
СписокОрганизаций.Добавить(объект.ВыбраннаяОрганизация);

Если объект.ВыбраннаяОрганизация = ПерваяОрганизация Тогда
    СписокОрганизаций.Добавить(СестраПервойОрганизации); 
КонецЕсли;

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    ХозрасчетныйОстатки.Счет,
|    ХозрасчетныйОстатки.СуммаОстаток
|ИЗ
|    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, , Организация В (&СписокОрганизаций),) КАК ХозрасчетныйОстатки";

Запрос.УстановитьПараметр("СписокОрганизаций", СписокОрганизаций);
Запрос.УстановитьПараметр("Дата", &Дата);

Результат = Запрос.Выполнить();

Этот метод оправдан, когда логика выбора организаций очень сложна и ее проще описать на языке 1С, чем на языке запросов.

← На главную