Почему данные в консоли запросов и в отчете СКД различаются?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет
← На главную

Разработка отчетов на Системе компоновки данных (СКД) часто преподносит сюрпризы: один и тот же запрос в консоли выдает корректные цифры, а в итоговом отчете поля остаются пустыми или значения искажаются. Рассмотрим эту ситуацию на примере доработки типового отчета «Продажи» в конфигурации «Управление нашей фирмой» (УНФ). Проанализируем, почему добавление нового регистра накопления в запрос может привести к потере данных и как это исправить.

Суть проблемы: неявное поведение СКД

Представим ситуацию: мы добавили в запрос отчета «Продажи» левое соединение с новым регистром СебестоимостьИзделий. В консоли запросов, где мы вручную устанавливаем параметры &НачалоПериода и &КонецПериода, всё работает идеально. Однако в режиме пользователя СКД начинает «оптимизировать» запрос. Главная причина расхождений заключается в том, что СКД — это не просто инструмент выполнения SQL-кода, а динамический конструктор, который пересобирает запрос перед исполнением, опираясь на настройки компоновки и параметры виртуальных таблиц.

Рассмотрим фрагмент запроса, который может вызывать затруднения при работе с виртуальными таблицами оборотов:


ВЫБРАТЬ
    ПродажиОбороты.Регистратор КАК Регистратор,
    ПродажиОбороты.Номенклатура,
    ПродажиОбороты.КоличествоОборот КАК Количество,
    ПродажиОбороты.СуммаОборот КАК Сумма,
    ПродажиОбороты.СебестоимостьОборот КАК Себестоимость,
    ВТСебестоимость.Себестоимость КАК СебестоимостьПоСпецификации
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ПродажиОбороты
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ
        СебестоимостьИзделияОбороты.Заказ,
        СУММА(СебестоимостьИзделияОбороты.СебестоимостьОборот) КАК Себестоимость
    ИЗ
        РегистрНакопления.СебестоимостьИзделия.Обороты() КАК СебестоимостьИзделияОбороты
    СГРУППИРОВАТЬ ПО
        СебестоимостьИзделияОбороты.Заказ
) КАК ВТСебестоимость
ПО ПродажиОбороты.ЗаказПокупателя = ВТСебестоимость.Заказ

Выясним причину, по которой поле СебестоимостьПоСпецификации может быть пустым в СКД. Когда мы не указываем параметры в скобках виртуальной таблицы Обороты(), СКД при включенном автозаполнении автоматически подставляет туда глобальные параметры периода отчета. Если данные в регистре СебестоимостьИзделия лежат за пределами выбранного периода (например, затраты были отражены в прошлом месяце, а продажа произошла в текущем), СКД просто не увидит эти записи, хотя в консоли без параметров они могли быть доступны.

Решение 1: Настройка параметров на вкладке «Компоновка данных»

Для того чтобы СКД не накладывала стандартный период на вспомогательные таблицы, нам необходимо управлять параметрами виртуальных таблиц явно. Разберем по шагам, как это сделать в конструкторе запроса схемы компоновки данных:

  1. Откроем конструктор запроса в наборе данных СКД.
  2. Перейдем на закладку Компоновка данных.
  3. В списке таблиц найдем нашу виртуальную таблицу (например, РегистрНакопления.СебестоимостьИзделия.Обороты).
  4. В нижней части окна перейдем на вкладку Параметры виртуальных таблиц.
  5. Здесь мы можем переопределить имена параметров. Если мы хотим, чтобы эта таблица игнорировала период отчета, мы можем оставить поля пустыми или задать им специфические имена, отличные от стандартных НачалоПериода и КонецПериода.

Проанализируем ситуацию: если в основном запросе используется &ПериодОтчета, а для себестоимости нам нужны данные за все время, мы можем использовать пустые значения в фигурных скобках в тексте запроса. Это будет выглядеть так:


ИЗ
    РегистрНакопления.СебестоимостьИзделия.Обороты({&НачалоПериода}, {&КонецПериода}, , ) КАК СебестоимостьИзделияОбороты

Использование фигурных скобок сообщает СКД, что эти параметры являются необязательными для данной таблицы и будут применены только в том случае, если они явно указаны в настройках компоновки для этого поля.

Решение 2: Отключение автозаполнения

В некоторых случаях механизм автозаполнения работает слишком агрессивно, добавляя лишние условия в секцию ГДЕ или в параметры виртуальных таблиц. Посмотрим, как изменение этой настройки влияет на результат. Если снять флаг Автозаполнение на уровне набора данных, СКД перестанет автоматически определять доступные поля и параметры.

Важный нюанс: при отключении автозаполнения нам придется вручную прописать все доступные поля на закладке Компоновка данных в конструкторе запроса. Это даст нам полный контроль над тем, какие условия и куда будут подставляться. Рассмотрим преимущества этого метода:

Решение 3: Правильное использование функций для работы с NULL

При левом соединении таблиц в СКД часто возникают проблемы с итогами и расчетами, если данные во второй таблице отсутствуют. Выясним, как правильно обрабатывать такие ситуации в выражениях полей и ресурсов.

В тексте запроса мы можем использовать стандартную функцию ЕСТЬNULL(Поле, 0). Однако СКД имеет свои особенности при расчете ресурсов. Посмотрим на пример вычисления валовой прибыли:


ВЫБОР
    КОГДА ВТСебестоимость.Себестоимость ЕСТЬ NULL
        ТОГДА ВТ.Сумма
    ИНАЧЕ ВТ.Сумма - ВТСебестоимость.Себестоимость
КОНЕЦ КАК ВаловаяПрибыльПоСпецификации

Для корректного отображения итогов в иерархии отчета рекомендуется выносить подобные расчеты на вкладку Ресурсы. Вместо того чтобы суммировать разность, вычисленную в запросе, правильнее написать выражение ресурса: Сумма(Сумма) - Сумма(СебестоимостьПоСпецификации). В этом случае СКД корректно обработает пустые значения на всех уровнях группировок.

Дополнительные факторы, влияющие на данные

Если вышеуказанные способы не помогли, проанализируем еще несколько технических моментов, специфичных для платформы 1С v8.3:

Подводя итог, можно сказать, что расхождение данных в консоли и СКД — это почти всегда следствие динамической модификации запроса. Всегда проверяйте параметры виртуальных таблиц на вкладке «Компоновка данных» и используйте фигурные скобки для управления поведением параметров периодов и отборов.

← На главную