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