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