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