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