При формировании складских отчетов нередко возникает задача найти позиции номенклатуры, остатки которых разбросаны по нескольким местам хранения (ячейкам). На первый взгляд может показаться, что достаточно сгруппировать данные по номенклатуре, вывести подчиненные строки ячеек и установить отбор по системному полю Номер по порядку в группировке больше единицы. Разберем, почему такой подход не сработает напрямую и как правильно решить эту задачу стандартными средствами системы компоновки данных (СКД).
Проанализируем внутренний механизм работы платформы 1С:Предприятие при формировании отчетов на СКД. Системные поля НомерПоПорядку и НомерПоПорядкуВГруппировке рассчитываются процессором вывода непосредственно в момент построения итогового табличного документа. К этому моменту все этапы компоновки данных, включая применение условий отбора, уже завершены.
По этой причине наложить отбор на системный номер строки невозможно ни на уровне отчета, ни на уровне конкретной группировки. Однако исходная задача состоит не в фильтрации конкретных номеров строк, а в подсчете количества связанных записей (ячеек) для каждого товара. Рассмотрим способы решения этой задачи как в пользовательском режиме, так и на уровне схемы компоновки данных в конфигураторе.
Если отчет уже внедрен в рабочую конфигурацию и мы не хотим вносить изменения в метаданные или создавать внешний отчет, настроим отбор через стандартный интерфейс редактирования варианта отчета. Разберем этот процесс по шагам:
Количество ячеек.Количество(Различные Ячейка). Строку детальных записей оставляем пустой.Количество ячеек, укажем вид сравнения Больше и значение 1.При таком подходе СКД посчитает число различных мест хранения для каждого товара и оставит в отчете только те позиции, у которых это значение строго больше единицы.
Если мы разрабатываем собственный отчет или дорабатываем существующую схему в конфигураторе, правильнее зафиксировать логику расчета на уровне ресурсов схемы:
Ячейка (или соответствующее поле места хранения).Количество(Различные Ячейка).Номенклатура, чтобы ресурс не вычислялся для детальных записей ячеек.Номенклатура перейдем на закладку Отбор и установим условие: Ячейка (Количество различных) Больше 1.Когда складской регистр содержит сотни тысяч записей, фильтрация средствами постобработки СКД может работать медленнее, так как платформа сначала выбирает все остатки в память, а затем отсекает лишнее. Оптимизируем выборку на уровне СУБД с помощью конструкции ИМЕЮЩИЕ (HAVING).
Посмотрим на пример текста запроса набора данных:
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_НоменклатураСДублямиЯчеек
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
СГРУППИРОВАТЬ ПО
Остатки.Номенклатура
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Остатки.Ячейка) > 1
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура,
Остатки.Ячейка КАК Ячейка,
Остатки.ВНаличииОстаток КАК ВНаличииОстаток
ИЗ
ВТ_НоменклатураСДублямиЯчеек КАК Дубль
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
ПО Дубль.Номенклатура = Остатки.Номенклатура
В этом запросе мы предварительно собираем только те товары, которые числятся более чем в одной ячейке, во временную таблицу ВТ_НоменклатураСДублямиЯчеек, а затем внутренним соединением получаем полные остатки только по отобранным позициям. Это существенно снижает нагрузку на сервер 1С и ускоряет вывод отчета.
Выделим ключевые моменты, на которые стоит обратить внимание при настройке отчета:
Отчет), условие может быть применено к записям до группировки, что приведет к некорректному результату или ошибке выполнения. Отбор всегда должен быть привязан к группировке Номенклатура.Количество(Различные Ячейка) игнорирует значения NULL. Если в системе часть остатков хранится без указания ячейки (пустая ссылка или NULL) и это состояние также требуется учитывать как отдельное место хранения, в запросе или вычисляемом поле необходимо предварительно обработать значение с помощью функции ЕСТЬNULL.