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