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