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

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

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

Суть проблемы и постановка задачи

Представим типичную задачу: необходимо построить отчет по движению денежных средств. Логика запроса строится следующим образом:

  1. Создается таблица всех дней из производственного календаря за выбранный период.
  2. Получаются остатки денежных средств на начало периода в разрезе банковских счетов.
  3. Эти данные соединяются так, чтобы на каждый день по каждому счету была зафиксирована сумма остатка на начало.
  4. К полученной таблице левым соединением добавляются обороты (график платежей) по конкретным дням.

Проблема проявляется на этапе расчета ресурсов. Даже если мы используем выражение типа ВычислитьВыражение("Максимум(СуммаОстаток)", "БанковскийСчет"), система может выводить некорректные данные. Самое странное в этой ситуации — избирательность ошибки: по большинству объектов (счетов) данные верны, а по некоторым — значения не имеют ничего общего с реальностью. При этом проверка в консоли запросов подтверждает, что исходная выборка данных корректна.

Разбор исходного запроса

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


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ДенежныеСредстваБезналичныеОстатки.БанковскийСчет КАК БанковскийСчет,
    ДенежныеСредстваБезналичныеОстатки.СуммаРеглОстаток КАК СуммаОстаток
ПОМЕСТИТЬ ОстаткиНаНачало
ИЗ
    РегистрНакопления.ДенежныеСредстваБезналичные.Остатки(&НачалоПериода, ) КАК ДенежныеСредстваБезналичныеОстатки
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ТаблицаДней.День КАК День,
    ОстаткиНаНачало.БанковскийСчет КАК БанковскийСчет,
    ОстаткиНаНачало.СуммаОстаток КАК СуммаОстаток
ПОМЕСТИТЬ ОстаткиПоДням
ИЗ
    ТаблицаДней КАК ТаблицаДней,
    ОстаткиНаНачало КАК ОстаткиНаНачало
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ОстаткиПоДням.День КАК День,
    ОстаткиПоДням.БанковскийСчет КАК БанковскийСчет,
    ЕСТЬNULL(ГрафикПоДням.СуммаОборот, 0) КАК СуммаОборот,
    ОстаткиПоДням.СуммаОстаток КАК СуммаОстаток
ИЗ
    ОстаткиПоДням КАК ОстаткиПоДням
    ЛЕВОЕ СОЕДИНЕНИЕ ГрафикПоДням КАК ГрафикПоДням
    ПО ОстаткиПоДням.День = ГрафикПоДням.День
        И ОстаткиПоДням.БанковскийСчет = ГрафикПоДням.БанковскийСчет

В данном запросе мы видим использование виртуальной таблицы Остатки. Именно здесь кроется корень проблемы при работе в режиме компоновки данных.

Выяснение причины: влияние параметра Период

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

Проанализируем механизм колонки Использование для параметров в СКД:

Почему установка значения «Всегда» для параметра «Период» ломает отчет?

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

Ошибки по конкретным счетам (а не по всем сразу) часто объясняются тем, как СУБД оптимизирует выполнение запроса. При наличии лишних или конфликтующих условий фильтрации, SQL-сервер может использовать разные индексы или планы запроса. Для счетов с небольшим количеством движений ошибка может быть незаметна, но там, где есть специфика (например, обороты в тот же день или остатки, пересчитанные из итогов), неверный параметр периода приводит к искажению результата.

Решение проблемы: правильная настройка параметров

Для исправления ситуации выполним следующие шаги в конструкторе схемы компоновки данных:

  1. Перейдем на закладку Параметры.
  2. Найдем в списке параметр с именем Период (он обычно создается системой автоматически и подсвечивается серым или имеет стандартную пометку).
  3. Проверим колонку Использование. Если там стоит значение Всегда, его необходимо изменить на Авто.
  4. Убедимся, что наши собственные параметры (например, &НачалоПериода и &КонецПериода) правильно связаны с полями или используются в тексте запроса.

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

Дополнительные рекомендации

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

Рассмотрим правильный вариант настройки ресурса для поля СуммаОстаток:

В колонке "Выражение" для итогов по банковскому счету следует использовать:

Максимум(СуммаОстаток)

Или, если используется сложная аналитика периодов:

ВычислитьВыражение("Максимум(СуммаОстаток)", "БанковскийСчет")

Важный нюанс: если вы хотите, чтобы остаток на начало периода не задваивался в общих итогах, но при этом корректно отображался в детальных записях по дням, внимательно следите за тем, какие параметры СКД считает «главными». Использование Авто позволяет системе гибко подставлять нужные даты, не конфликтуя с вашим кодом на языке запросов 1С.

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

← На главную