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