При работе с конфигурацией «Управление торговлей 11» (а также ERP и «Комплексная автоматизация») часто возникает задача анализа данных в регистре накопления Выручка и себестоимость продаж. Одной из типичных проблем для начинающих разработчиков становится необходимость отфильтровать данные не по одной, а по списку конкретных хозяйственных операций. Разберем детально, как реализовать такой отбор различными способами, от простого перечисления в тексте запроса до динамического формирования списка в программном коде.
Самый эффективный и лаконичный способ отобрать несколько значений — использовать оператор В. Это позволяет избежать нагромождения условий и делает запрос легко читаемым. Рассмотрим пример, когда нам нужно получить данные только по операциям реализации и авансовым отчетам. Проанализируем структуру запроса:
ВЫБРАТЬ
Продажи.ХозяйственнаяОперация,
Продажи.СуммаВыручкиОборот
ИЗ
РегистрНакопления.ВыручкаСебестоимостьПродажи.ОБОРОТЫ(
&НачалоПериода,
&КонецПериода,
,
ХозяйственнаяОперация В (
ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.РеализацияКлиенту),
ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.АвансовыйОтчет)
)
) КАК Продажи
В данном примере мы используем конструкцию ЗНАЧЕНИЕ(Перечисление.ИмяПеречисления.ИмяЗначения). Это позволяет жестко зафиксировать список операций прямо в коде запроса. Обратите внимание, что отбор накладывается в параметрах виртуальной таблицы Обороты, что крайне важно для производительности системы.
Если по каким-то причинам вы не хотите использовать оператор В, можно воспользоваться классическим логическим сложением. Выясним причину, почему этот метод менее предпочтителен: при большом количестве операций (например, более 5–10) текст запроса становится трудночитаемым, однако для 2–3 значений он вполне допустим.
Пример реализации через логическое ИЛИ:
ГДЕ
ХозяйственнаяОперация = ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.РеализацияКлиенту)
ИЛИ ХозяйственнаяОперация = ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.РеализацияЧерезКомиссионера)
Посмотрим на этот код: система будет проверять каждое условие последовательно. Важно помнить, что если вы используете ГДЕ вне параметров виртуальной таблицы, запрос сначала выберет все записи из базы, а потом начнет их фильтровать, что существенно замедлит работу на больших объемах данных.
Часто список хозяйственных операций заранее неизвестен или должен настраиваться пользователем. В этом случае мы используем параметр-список. Разберем по шагам, как это реализовать в коде 1С:
СписокЗначений.Проанализируем пример программного кода:
// 1. Подготавливаем список операций
СписокОпер = Новый СписокЗначений;
СписокОпер.Добавить(Перечисления.ХозяйственныеОперации.РеализацияКлиенту);
СписокОпер.Добавить(Перечисления.ХозяйственныеОперации.ВозвратТоваровОтКлиента);
// 2. Создаем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Выручка.СуммаВыручкиОборот
|ИЗ
| РегистрНакопления.ВыручкаСебестоимостьПродажи.ОБОРОТЫ(,, , ХозяйственнаяОперация В (&СписокОпераций)) КАК Выручка";
// 3. Устанавливаем параметр
Запрос.УстановитьПараметр("СписокОпераций", СписокОпер);
Результат = Запрос.Выполнить();
Важный технический нюанс: при программном заполнении желательно явно указывать тип элементов списка значений. Это помогает избежать ошибок сопоставления типов в сложных запросах. Для этого можно использовать СписокОпер.ТипЗначений = Новый ОписаниеТипов("ПеречислениеСсылка.ХозяйственныеОперации");.
Если вы предпочитаете визуальные инструменты разработки, разберем, как настроить такой отбор в Конструкторе запросов 1С:
ХозяйственнаяОперация.= (равно) выберите или напишите вручную оператор В.&СписокХозопераций), либо выбрать конкретные значения из перечисления, если список статичен. Конструктор автоматически сгенерирует правильный синтаксис В (ЗНАЧЕНИЕ(...)).Рассмотрим подробнее вопрос производительности. Регистр Выручка и себестоимость продаж в крупных базах УТ 11 может содержать миллионы записей.
Когда мы пишем условие внутри скобок виртуальной таблицы Обороты(..., ХозяйственнаяОперация В (...)), платформа 1С передает этот фильтр непосредственно СУБД (SQL Server или PostgreSQL). База данных отсекает ненужные записи еще на этапе чтения с диска.
Если же мы напишем условие в секции ГДЕ, СУБД сначала сформирует таблицу всех оборотов за период, передаст их на сервер приложений 1С, и только потом 1С отфильтрует лишнее. Это критическая ошибка, которой следует избегать при разработке отчетов.
Иногда ситуация бывает обратной: нам нужны почти все операции, кроме одной или двух (например, нужно исключить внутренние перемещения). В таком случае проще использовать отрицание НЕ В. Это значительно сокращает текст запроса и упрощает его поддержку.
ХозяйственнаяОперация НЕ В (
ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.ПередачаМеждуОрганизациями),
ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.ПеремещениеТоваров)
)
Если вы разрабатываете отчет на СКД, старайтесь не прописывать список операций жестко в тексте запроса. Проанализируем правильный подход для СКД:
ХозяйственнаяОперация в настройки отбора на закладке «Настройки» компоновщика.Таким образом, мы рассмотрели все основные способы реализации отбора по нескольким значениям. Наиболее универсальным и производительным является использование оператора В внутри параметров виртуальной таблицы.