При разработке отчетов типа «Товарный календарь» или кросс-таблиц программисты часто сталкиваются с задачей: нужно скрыть строки, итоговый результат которых не соответствует условию (например, общий остаток на конец периода равен нулю или приход меньше расхода). Если применить обычный отбор по ресурсу, система может начать фильтровать каждую детальную запись или отдельные колонки-периоды, что приведет к искажению данных. В этой статье мы разберем несколько эффективных способов реализации отбора именно по итоговому значению строки.
Это самый простой и рекомендуемый способ, если вы хотите оставить пользователю возможность менять условия отбора в пользовательских настройках. Основная ошибка заключается в установке отбора на уровне всего отчета. Вместо этого мы настроим отбор для конкретной группировки строк.
Рассмотрим по шагам, как это сделать в схеме компоновки данных:
Номенклатура).Остаток), установим вид сравнения Меньше и значение 0.Проанализируем ситуацию: если оставить значение «Всюду», СКД попытается применить фильтр ко всем исходным записям еще до расчета итогов. Выбрав «После группировки», мы заставляем систему сначала вычислить сумму по всей строке номенклатуры за все дни, а уже потом проверить условие. Если итог по строке не удовлетворяет условию, вся строка целиком будет исключена из результата.
Если структура отчета фиксированная и нам нужно жестко ограничить выборку данных для повышения производительности, лучше всего сделать это на уровне SQL-запроса. Для этого используется конструкция ИМЕЮЩИЕ (HAVING).
Разберем пример запроса, который выбирает данные и сразу отсекает строки с нулевым итоговым количеством:
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.Количество) КАК КоличествоИтог
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
ИМЕЮЩИЕ
СУММА(Продажи.Количество) > 0
Этот метод работает быстрее всего, так как база данных передает в систему компоновки уже отфильтрованный набор данных. Однако стоит учитывать, что в этом случае пользователь не сможет легко отключить этот фильтр в настройках отчета.
Если отчет сложный и строится на детальных записях (например, регистрация движений по дням), можно использовать подход с предварительным расчетом итогов во временной таблице. Рассмотрим пример кода запроса, который сначала вычисляет общие итоги, а затем соединяет их с детальными данными:
// Помещаем все детальные данные во временную таблицу
ВЫБРАТЬ
Данные.Склад КАК Склад,
Данные.Номенклатура КАК Номенклатура,
Данные.Дата КАК Дата,
Данные.Количество КАК Количество
ПОМЕСТИТЬ втДанные
ИЗ
Документ.АвансовыйОтчет.Товары КАК Данные;
////////////////////////////////////////////////////////////////////////////////
// Вычисляем итоги и отбираем только нужные позиции
ВЫБРАТЬ
втДанные.Склад КАК Склад,
втДанные.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ втОтборИтогов
ИЗ
втДанные КАК втДанные
СГРУППИРОВАТЬ ПО
втДанные.Склад,
втДанные.Номенклатура
ИМЕЮЩИЕ
СУММА(втДанные.Количество) > 1000;
////////////////////////////////////////////////////////////////////////////////
// Выводим детальные записи только для тех позиций, которые прошли отбор по итогу
ВЫБРАТЬ
втДанные.Склад КАК Склад,
втДанные.Номенклатура КАК Номенклатура,
втДанные.Дата КАК Дата,
втДанные.Количество КАК Количество
ИЗ
втДанные КАК втДанные
ГДЕ
(втДанные.Склад, втДанные.Номенклатура) В
(ВЫБРАТЬ втОтборИтогов.Склад, втОтборИтогов.Номенклатура ИЗ втОтборИтогов)
Такой подход позволяет сохранить в отчете детальную информацию (например, обороты по дням), но при этом полностью скрыть те товары или склады, общий оборот по которым не превысил заданный порог.
В СКД существует мощный механизм функций языка выражений. Мы можем создать вычисляемое поле, которое будет содержать итог по всей группировке, независимо от того, в какой ячейке таблицы оно отображается.
Проанализируем шаги настройки:
ОбщийОстатокПоСтроке.ВычислитьВыражение("Сумма(Остаток)", "Номенклатура", "ОбщийИтог").Функция ВычислитьВыражение с параметром "ОбщийИтог" позволяет «заглянуть» в финальный результат расчета агрегата. Даже если отчет развернут по дням, в каждой колонке для данной строки будет стоять одно и то же число — финальный итог. Отбор по такому полю корректно скроет всю строку.
Если вы не хотите менять структуру запроса, можно воспользоваться пользовательскими полями (вкладка «Настройки» -> «Пользовательские поля»).
Выясним, как это работает: мы создаем новое поле «Поле выражение». В итоговых записях мы прописываем формулу ресурса, а в детальных записях устанавливаем значение 0 или NULL. В дальнейшем в настройках отбора мы указываем условие именно для этого пользовательского поля. Это позволяет визуально отделить логику фильтрации от основных ресурсов отчета.
Резюме: выбор метода зависит от ваших целей. Для максимальной гибкости пользователя используйте отбор в группировке с признаком «После группировки». Для сложных расчетов и оптимизации скорости — временные таблицы или условие ИМЕЮЩИЕ в тексте запроса.