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