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