При разработке сложных отчетов в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда установленный отбор (например, по организации или складу) игнорируется запросом. В итоге в выборку попадают лишние данные, которых там быть не должно. Особенно часто это происходит в многослойных запросах с использованием временных таблиц, объединений (ОБЪЕДИНИТЬ ВСЕ) и левых соединений. Проанализируем, почему это происходит и как правильно настроить фильтрацию данных.
Рассмотрим типовой сценарий. У нас есть сложный запрос, который собирает данные из регистра накопления СебестоимостьТоваров, использует временные таблицы для сегментов номенклатуры и выполняет расчеты цен. Автор темы столкнулся с тем, что в итоговый отчет попадает номенклатура, которая не числится за выбранной организацией. Выясним причину этой проблемы.
Основная причина кроется в том, как именно накладывается отбор. Если отбор устанавливается программно или через настройки компоновки данных (СКД) "поверх" запроса, система не всегда может корректно прокинуть этот фильтр внутрь вложенных запросов или временных таблиц. Рассмотрим структуру проблемного запроса:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
...
СебестоимостьТоваров.Организация КАК Организация
ПОМЕСТИТЬ Итог
ИЗ (
ВЫБРАТЬ ...
ЛЕВОЕ СОЕДИНЕНИЕ РасчетыСебестоимости ПО ...
ГДЕ ...
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ...
ИЗ РегистрНакопления.СебестоимостьТоваров.Остатки(...)
) КАК СебестоимостьТоваров
Когда мы используем ЛЕВОЕ СОЕДИНЕНИЕ, записи из левой таблицы выбираются в любом случае. Если условие отбора по организации наложено только в конечном выборе или некорректно прописано во вложенных частях ОБЪЕДИНИТЬ ВСЕ, данные из "левой" части таблицы могут попасть в результат с пустым значением организации или со значением другой организации, если фильтр не дошел до источника данных.
Самый надежный способ гарантировать работу отбора — передать его в запрос через параметр. Вместо того чтобы полагаться на внешние механизмы платформы, мы добавим условие непосредственно в текст запроса. Посмотрим на пример реализации:
В итоговой секции запроса или во временной таблице, где формируются финальные данные, необходимо добавить жесткое условие:
ГДЕ
Итог.Организация = &Организация
Проанализируем этот подход. Использование параметра &Организация гарантирует, что на уровне СУБД будет выполнена фильтрация еще до того, как данные попадут в итоговую выборку. Если вы используете временные таблицы, убедитесь, что поле Организация присутствует в каждой из них, чтобы вы могли наложить фильтр на любом этапе сборки данных.
Работа с регистрами накопления в 1С (остатками и оборотами) требует особого внимания к производительности. Если мы накладываем отбор в секции ГДЕ, система сначала выбирает все записи из регистра, а затем отсеивает лишние. Рассмотрим, как сделать это правильно с помощью параметров виртуальной таблицы.
Вместо обращения к виртуальной таблице без фильтров, укажем их внутри скобок:
ИЗ РегистрНакопления.СебестоимостьТоваров.Остатки(&Период, {Организация.* КАК Организация})
Здесь мы используем фигурные скобки {}. Это специальный синтаксис системы компоновки данных (СКД). Рассмотрим подробнее, что он дает:
Иногда отбор не срабатывает из-за того, что платформа 1С не может однозначно определить тип поля во временной таблице. Это часто случается, когда поле получается в результате выбора (ВЫБОР КОГДА...) или объединения таблиц с разными типами. Выясним, как это исправить.
Рекомендуется явно типизировать поле Организация с помощью функции ВЫРАЗИТЬ. Это исключит ситуацию, когда поле принимает тип "ЛюбаяСсылка", из-за чего стандартный поиск по конкретной ссылке организации может работать некорректно.
ВЫРАЗИТЬ(ДанныеДокумента.Организация КАК Справочник.Организации) КАК Организация
Проанализируем ситуацию с NULL значениями. В запросах с левыми соединениями поле организации может стать NULL, если соответствие не найдено. В этом случае обычный отбор Организация = &Организация просто отсечет такие строки (так как NULL не равен значению ссылки). Если вам нужно сохранить такие строки, используйте ЕСТЬNULL, но для строгих отборов по организации это обычно не требуется.
Если отбор все равно не работает, выполните следующие действия по шагам:
&Организация вручную. Если в консоли данные фильтруются правильно, значит, проблема в настройках СКД или программном коде вызова запроса.Организация установлена роль "Измерение", если данные берутся из регистров.ОБЪЕДИНИТЬ ВСЕ), проверьте, чтобы во всех объединяемых частях поле Организация имело одинаковый псевдоним и тип данных.Итог (или аналогичную) попадает именно ссылка на организацию, а не строка или другое представление.Важный момент: При работе в Управляемом приложении помните о кэшировании. Если вы изменили текст запроса в схеме компоновки, иногда требуется перезагрузить настройки отчета в пользовательском режиме (кнопка "Установить стандартные настройки"), чтобы новые поля и условия отбора вступили в силу.
Таким образом, для решения проблемы "несрабатывающего" отбора мы должны комбинировать явное указание параметров в тексте запроса (&Организация) и использование механизмов СКД (фигурные скобки {}) в параметрах виртуальных таблиц. Это обеспечит и корректность данных, и высокую скорость работы отчета.