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

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке отчетов в системе компоновки данных (СКД) на платформе 1С:Предприятие разработчики часто сталкиваются с задачей настройки гибких фильтров. Типичный сценарий: в отчете есть параметры Номенклатура и Склад. Требуется, чтобы при заполнении обоих полей отчет фильтровался по обоим значениям, при заполнении только одного из них — по этому значению, а при пустых параметрах — выводились все данные без ограничений.

Попытки решить эту задачу «в лоб» через изменение стандартного текста запроса часто приводят к неоптимальной работе базы данных и логическим ошибкам. В этой статье мы подробно разберем, почему популярные «самописные» конструкции в запросах вредны, и рассмотрим правильные, высокопроизводительные способы реализации необязательных отборов средствами СКД.

Анализ неверного решения: почему конструкция «ВЫБОР КОГДА» в параметрах — это плохой путь?

В попытках решить проблему авторы часто прибегают к использованию условного оператора ВЫБОР непосредственно внутри параметров виртуальных таблиц. Типичный пример такого кода выглядит следующим образом:


РегистрНакопления.ТоварыОрганизаций.Остатки(
    ,
    ВЫБОР
        КОГДА &Номенклатура = НЕОПРЕДЕЛЕНО
            ИЛИ &Номенклатура = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
        ТОГДА ИСТИНА
        ИНАЧЕ АналитикаУчетаНоменклатуры.Номенклатура В ИЕРАРХИИ (&Номенклатура)
    КОНЕЦ
    И ВЫБОР
        КОГДА &Склад = НЕОПРЕДЕЛЕНО
            ИЛИ &Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
        ТОГДА ИСТИНА
        ИНАЧЕ АналитикаУчетаНоменклатуры.Склад В ИЕРАРХИИ (&Склад)
    КОНЕЦ)

Рассмотрим подробнее, к каким серьезным проблемам ведет этот подход:

  1. Катастрофическое падение производительности (Anti-pattern). Когда СУБД (например, MS SQL Server или PostgreSQL) получает запрос с конструкцией ВЫБОР КОГДА... в секции условий, она не может построить эффективный план запроса. Оптимизатор СУБД лишается возможности использовать индексы таблиц для быстрого поиска (Index Seek). Вместо этого СУБД будет вынуждена выполнять полное сканирование таблиц или индексов (Table/Index Scan). На реальной базе данных с сотнями тысяч записей такой отчет гарантированно вызовет зависание системы и избыточную нагрузку на сервер.
  2. Логические ошибки при объединении таблиц. Если ваш запрос состоит из нескольких объединяемых подзапросов (например, остатки по организациям, остатки на складах и остатки в ячейках) и вы примените данную конструкцию только к одной из таблиц, отчет вернет некорректные данные. Пустые параметры в необработанных подзапросах полностью отсекут результаты из этих ветвей объединения.
  3. Логические нестыковки в связанных реквизитах. В запросах к адресным складам часто встречается ошибка адресации владельца ячейки. Например, условие вида Ячейка.Владелец = &Номенклатура И Ячейка.Владелец = &Склад принципиально неверно, так как владелец ячейки — это всегда конкретный склад (или зона), но никак не номенклатурная позиция.

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

Решение А. Использование расширения языка запросов СКД (Фигурные скобки)

Система компоновки данных предоставляет мощный механизм — расширение языка запросов. С его помощью мы можем указать платформе, какие условия и параметры являются необязательными. Если пользователь оставляет поле отбора пустым, СКД автоматически и бесследно удаляет соответствующее условие из итогового SQL-запроса, отправляемого к СУБД. Это гарантирует максимальную скорость выполнения.

Для реализации этого метода мы используем фигурные скобки {} внутри параметров виртуальных таблиц. Перепишем исходный запрос правильно:


ВЫБРАТЬ
    ЗапросПоДанным.Номенклатура КАК Номенклатура,
    СУММА(ЗапросПоДанным.ТоварыОрганизаций) КАК ТоварыОрганизаций,
    СУММА(ЗапросПоДанным.ТоварыНаСкладах) КАК ТоварыНаСкладах,
    СУММА(ЗапросПоДанным.ТоварыВЯчейках) КАК ТоварыВЯчейках,
    ЗапросПоДанным.Номенклатура.Код КАК Код,
    ЗапросПоДанным.Номенклатура.Артикул КАК Артикул
ИЗ
    (ВЫБРАТЬ
        ТоварыОрганизацийОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
        ТоварыОрганизацийОстатки.КоличествоОстаток КАК ТоварыОрганизаций,
        0 КАК ТоварыНаСкладах,
        0 КАК ТоварыВЯчейках
    ИЗ
        РегистрНакопления.ТоварыОрганизаций.Остатки(, {(АналитикаУчетаНоменклатуры.Номенклатура).* КАК Номенклатура, (АналитикаУчетаНоменклатуры.Склад).* КАК Склад}) КАК ТоварыОрганизацийОстатки
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ТоварыНаСкладахОстатки.Номенклатура,
        0,
        ТоварыНаСкладахОстатки.ВНаличииОстаток,
        0
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(, {(Номенклатура).* КАК Номенклатура, (Склад).* КАК Склад}) КАК ТоварыНаСкладахОстатки
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ТоварыВЯчейкахОстатки.Номенклатура,
        0,
        0,
        ТоварыВЯчейкахОстатки.ВНаличииОстаток
    ИЗ
        РегистрНакопления.ТоварыВЯчейках.Остатки(, {(Номенклатура).* КАК Номенклатура, (Ячейка.Владелец).* КАК Склад}) КАК ТоварыВЯчейкахОстатки) КАК ЗапросПоДанным

СГРУППИРОВАТЬ ПО
    ЗапросПоДанным.Номенклатура,
    ЗапросПоДанным.Номенклатура.Код,
    ЗапросПоДанным.Номенклатура.Артикул

Разберем детально синтаксис фигурных скобок в данном примере:

Важный шаг настройки в схеме СКД: после изменения текста запроса перейдите на вкладку Параметры в конструкторе макета компоновки данных. Для параметров &Номенклатура и &Склад установите флаг Ограничение доступности. Нам больше не нужно заставлять пользователя вводить параметры напрямую. Вместо этого выведите поля «Номенклатура» и «Склад» в список доступных отборов на вкладке Настройки (в окне «Отбор»).

Решение Б. Настройка через визуальный Конструктор запроса СКД

Если вы предпочитаете не писать фигурные скобки вручную, этот функционал можно легко настроить с помощью визуального интерфейса платформы. Разберем этот процесс по шагам:

  1. Откройте нужный набор данных (запрос) в схеме компоновки данных и запустите Конструктор запроса.
  2. Перейдите на вкладку Компоновка данных (обратите внимание, что вам нужна именно эта вкладка, а не стандартная вкладка «Условия»).
  3. Внутри этой вкладки перейдите на вложенную вкладку Таблицы.
  4. Перетащите необходимые виртуальные таблицы остатков из левого списка в правое окно «Используемые таблицы».
  5. Выделите таблицу (например, ТоварыНаСкладах.Остатки) и нажмите кнопку выбора параметров виртуальной таблицы (иконка в виде шестеренки).
  6. В появившемся диалоговом окне перейдите к строкам параметров и укажите доступные поля компоновки для отбора (Номенклатура, Склад).
  7. Нажмите «ОК». Конструктор самостоятельно сформирует правильный синтаксис расширения языка запросов с фигурными скобками в тексте вашего запроса.

Альтернативный вариант: классический отбор для простых запросов (вне СКД)

В редких случаях, когда аналогичную задачу нужно решить в обычном запросе вне рамок СКД (например, в коде обработки или в динамическом списке без поддержки компоновки), использование расширения языка запросов невозможно. Чтобы избежать использования медленной конструкции ВЫБОР КОГДА, применяется классическое условие с использованием оператора ИЛИ:


ГДЕ
    (Номенклатура = &Номенклатура ИЛИ &Номенклатура = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка))
    И (Склад = &Склад ИЛИ &Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка))

Этот вариант обрабатывается СУБД значительно эффективнее, чем условные конструкции ВЫБОР, хотя по скорости всё же уступает динамическому формированию текста запроса в коде. В коде на встроенном языке 1С наилучшей практикой является конструирование строки условий ГДЕ только при фактическом заполнении соответствующих переменных.

Подводя итоги, отметим: для любых отчетов, разрабатываемых на базе СКД, единственным верным и профессиональным решением является использование механизмов компоновки данных (фигурных скобок) или визуальной настройки параметров виртуальных таблиц на вкладке «Компоновка данных» конструктора. Это гарантирует быструю работу вашей базы данных и корректность получаемых результатов.

← На главную