При построении отчетов по продажам часто возникает задача исключить из итоговых показателей «шум» — мелкие реализации, которые не должны влиять на общую статистику. Стандартная установка условия в секции ГДЕ или использование отбора в Системе компоновки данных (СКД) часто приводит к тому, что система фильтрует уже суммированный результат по группировке (например, по номенклатуре), а не каждую отдельную операцию. Разберем подробно, как заставить 1С анализировать каждую строку документа до того, как цифры сложатся в итоговый отчет.
Проанализируем типичную ситуацию. Если мы пишем запрос к виртуальной таблице Продажи.Обороты и ставим условие ГДЕ КоличествоОборот > 10, система сначала сгруппирует данные за период по измерениям (например, по товару), а затем проверит, превышает ли общая сумма 10 единиц. Если же наша задача — убрать из расчета чеки, где продано по 1-2 штуке, но оставить товар в отчете, если в сумме по другим чекам набралось много, обычный фильтр не сработает.
Выясним причину такого поведения: виртуальные таблицы без указания периодичности «Регистратор» выдают уже агрегированные данные. Нам же нужно спуститься на уровень ниже.
Это классический метод, который в итоге помог автору темы. Суть заключается в том, чтобы сначала выбрать все детальные записи с нужным фильтром, а затем использовать этот результат как источник для итогового суммирования. Рассмотрим пример структуры такого запроса:
ВЫБРАТЬ
ВложенныйЗапрос.Номенклатура КАК Номенклатура,
СУММА(ВложенныйЗапрос.Количество) КАК КоличествоИтого
ИЗ
(ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
Продажи.Количество КАК Количество
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Количество > &Порог) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Номенклатура
В данном примере мы обращаемся к физической таблице регистра. Условие ГДЕ внутри вложенного запроса отсекает строки с малым количеством на уровне записей базы данных. В основной (внешний) запрос попадают только те данные, которые прошли «ценз», и функция СУММА корректно их складывает.
Если нам необходимо использовать именно виртуальную таблицу Обороты (например, чтобы получить обороты в разрезе периодов или использовать дополнительные поля), мы можем включить периодичность Регистратор. Посмотрим, как это работает:
Регистратор.Регистратор в список выборки.ГДЕ КоличествоОборот > &МинимальноеЗначение.Поскольку теперь таблица не сворачивает данные по номенклатуре, а выдает их по каждому документу, условие применится именно к строкам документов. Однако помните: если вы используете СКД, и поле Регистратор не выбрано в настройках отчета (вкладка «Настройки»), СКД может оптимизировать запрос и выкинуть это поле, что снова приведет к некорректному суммированию. Чтобы этого избежать, установите у поля флаг «Обязательное» в схеме компоновки данных.
Разберем еще один изящный способ, который позволяет избежать сложных вложенных конструкций и сохранить высокую производительность. Мы можем использовать оператор ВЫБОР прямо в тексте запроса или в вычисляемых полях СКД.
ВЫБРАТЬ
Продажи.Номенклатура,
СУММА(ВЫБОР
КОГДА Продажи.Количество > &Порог
ТОГДА Продажи.Количество
ИНАЧЕ 0
КОНЕЦ) КАК КоличествоДляРасчета
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
Этот метод хорош тем, что мы не «выбрасываем» записи совсем, а просто обнуляем их вклад в общую сумму. Это позволяет, например, в одном отчете видеть и реальные общие продажи, и «очищенные» показатели рядом, используя разные ресурсы.
Если отчет строится полностью на СКД, мы можем реализовать логику фильтрации детальных записей на уровне ресурсов. Это самый гибкий метод для пользователя.
Проделаем следующие шаги:
КоличествоБольшеПорога.ВЫБОР КОГДА Количество > &МинимальныйПорог ТОГДА Количество ИНАЧЕ 0 КОНЕЦ.СУММА(КоличествоБольшеПорога).Таким образом, в детальных записях отчета (если их вывести) пользователь увидит все строки, но в итогах по папкам и товарам будут фигурировать только те данные, которые превышают заданный порог. Это создает «мега шикарный отчет», как выразился автор темы, где можно сравнивать разные типы продаж (пиковые, сглаженные, постоянные) в рамках одного набора данных.
Проанализируем ситуацию с точки зрения нагрузки на сервер. Использование вложенных запросов в 1С (особенно если их много) может негативно сказываться на планах запросов SQL-сервера. Если данных очень много, рассмотрим более профессиональный подход — Временные таблицы. Сначала поместим отфильтрованные детальные записи во временную таблицу, проиндексируем их по Номенклатуре, и только потом выполним итоговое суммирование. Это обеспечит максимальную скорость работы отчета на больших объемах данных.
Подводя итог: для решения задачи отсечения мелких записей наиболее эффективными являются либо использование физических таблиц с вложенным запросом, либо применение оператора ВЫБОР в ресурсах СКД. Выбор зависит от того, нужно ли вам полностью скрыть эти записи из отчета или просто исключить их из итоговой суммы.