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