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

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

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

Причина проблемы: Механизм оптимизации и «Автозаполнение»

Главное отличие СКД от обычной консоли запросов заключается в том, что СКД — это не просто инструмент для выполнения текста запроса. Это мощный генератор, который перестраивает ваш исходный текст перед выполнением. Если в настройках схемы (на закладке «Набор данных») включен флаг Автозаполнение, система анализирует, какие поля выбрал пользователь в настройках отчета, какие группировки и отборы установлены.

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

Решение 1: Использование вычисляемых полей и ресурсов

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

Рассмотрим алгоритм действий:

  1. В тексте запроса оставляем только выборку детальных данных:
    
    ВЫБРАТЬ
        Таб.Номенклатура КАК Номенклатура,
        Таб.ДатаКалендаря КАК ДатаКалендаря,
        Таб.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток
    ИЗ
        ТаблицаОстатковПоДням КАК Таб
    
  2. Переходим на закладку Вычисляемые поля и добавляем новое поле, например, ДеньОтсутствия. В выражении пишем: ВЫБОР КОГДА КоличествоКонечныйОстаток <= 0 ТОГДА 1 ИНАЧЕ 0 КОНЕЦ.
  3. На закладке Ресурсы определяем, как это поле будет суммироваться. Чтобы гарантировать корректность, можно использовать выражение: СУММА(ДеньОтсутствия) или более надежный вариант через уникальные даты: КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВЫБОР КОГДА КоличествоКонечныйОстаток <= 0 ТОГДА ДатаКалендаря КОНЕЦ).

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

Решение 2: Свойство поля «Обязательное»

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

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

Решение 3: Правильная настройка ролей полей

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

Проанализируем шаги настройки роли:

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

Решение 4: Разделение запросов и вложенные выборки

Иногда оптимизатор СКД слишком агрессивно перестраивает вложенные запросы. Рассмотрим вариант, предложенный участниками форума: разделение логики. Вместо того чтобы суммировать в том же запросе, где проверяется условие <= 0, попробуйте сначала сформировать поле-флаг (0 или 1) во временной таблице, а итоговое суммирование делать в финальном ВЫБРАТЬ.

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

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

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

В этом случае мы берем управление в свои руки:

  1. Снимаем галочку Автозаполнение под текстом запроса.
  2. Используем синтаксис фигурных скобок {} внутри текста запроса для описания полей, которые СКД может использовать для отборов, группировок и выбора.

Пример части запроса с ручным управлением:


ВЫБРАТЬ
    Таб.Номенклатура КАК Номенклатура,
    {Таб.Номенклатура.* КАК Номенклатура},
    СУММА(ВЫБОР КОГДА Таб.КоличествоКонечныйОстаток <= 0 ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК КоличествоДнейОтсутствия
ИЗ
    ТаблицаОстатковПоДням КАК Таб
ГРУППИРОВАТЬ ПО
    Таб.Номенклатура
{ГРУППИРОВАТЬ ПО
    Номенклатура}

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

Подведем итоги

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

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

← На главную