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

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

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

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

Выясняем причину: эффект неявного «Внутреннего соединения»

Проанализируем ситуацию, которая происходит в системе компоновки данных по умолчанию. Когда мы связываем два набора данных (например, «НаборДанных1» — основной запрос, и «НаборДанных2» — подчиненный запрос или выборка из регистра) на вкладке «Связи наборов данных», платформа 1С пытается объединить их по ключевым полям.

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

Однако поведение оптимизатора СКД меняется, если мы добавляем новое поле из подчиненного набора данных напрямую в выбранные поля отчета как обычный реквизит или измерение. В этот момент левое соединение наборов данных неявно для разработчика превращается во внутреннее соединение (INNER JOIN). Происходит это по следующим причинам:

  1. Ограничения детальных записей: Если СКД выводит поле из подчиненного набора как обычное нересурсное поле в детальных записях, система пытается сопоставить физические строки наборов данных еще на этапе компоновки результата. Если соответствия в подчиненном наборе нет, оптимизатор СКД может просто отбросить родительскую строку, посчитав ее нерелевантной.
  2. Глобальные отборы: Если на отчет наложен общий отбор по любому из полей подчиненного набора данных, СКД автоматически перестраивает результирующий запрос во внутреннее соединение, исключая пустые строки.
  3. Использование в собственных макетах: При выводе нересурсного поля в область макета (шапки или ячеек) СКД жестко привязывается к структуре группировок. Отсутствие данных во втором наборе приводит к невозможности корректного вывода области, из-за чего скрывается вся строка или секция отчета.

Решение 1. Перенос поля на вкладку «Ресурсы»

Самый простой и быстрый способ вернуть пропавшие данные в отчет — это объявить добавленное поле подчиненного набора данных ресурсом в СКД. Разберем по шагам, почему это работает и как это правильно настроить.

В СКД расчет обычных полей и полей-ресурсов происходит на принципиально разных этапах компоновки:

Выполним настройку поля-ресурса по шагам:

  1. Откройте схему компоновки данных вашего отчета и перейдите на вкладку «Ресурсы».
  2. В левом списке найдите ваше новое поле, которое вы добавили из второго набора данных (например, это может быть дата последнего события, статус или представление дополнительного реквизита).
  3. Перенесите это поле в правый список доступных ресурсов с помощью стрелок или двойного клика мыши.
  4. В колонке «Выражение» задайте для этого поля подходящую агрегатную функцию. Если ваше поле является числовым, выберите функцию Сумма(ИмяВашегоПоля). Если поле имеет тип Дата, Строка или Булево, используйте функцию Максимум(ИмяВашегоПоля) или Минимум(ИмяВашегоПоля).
  5. В колонке «Рассчитывать по...» вы можете указать конкретные группировки или оставить поле пустым, чтобы ресурс рассчитывался для всех уровней отчета, включая детальные записи.

После этого вернитесь в настройки отчета на вкладку «Выбранные поля» и убедитесь, что новое поле теперь отображается со значком ресурса (обычно это синий или зеленый значок функции). Запустите отчет — данные основного набора вернутся на место, а в новой колонке отобразятся нужные значения либо пустые ячейки там, где данных во втором наборе не оказалось.

Решение 2. Объединение наборов данных на уровне SQL-запроса (Оптимизация)

Связывание наборов данных непосредственно в СКД средствами платформы «1С:Предприятие» — это удобный инструмент, но он имеет два существенных недостатка: он работает медленнее, чем соединение таблиц на уровне СУБД, и часто приводит к непредсказуемому поведению оптимизатора (как в случае с пропавшими данными).

Если оба ваших набора данных являются запросами к одной и той же базе данных, мы настоятельно рекомендуем отказаться от связей наборов в СКД и объединить их в один пакетный запрос с использованием классического ЛЕВОЕ СОЕДИНЕНИЕ. Это гарантирует 100% стабильность вывода данных и существенно ускорит работу отчета.

Рассмотрим пример того, как переписать два связанных набора данных в один оптимальный пакетный запрос:


ВЫБРАТЬ
    ПродажиОбороты.Контрагент КАК Контрагент,
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.СуммаОборот КАК СуммаПродаж
ПОМЕСТИТЬ ВТ_ОсновныеДанные
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОсновныеДанные.Контрагент КАК Контрагент,
    ВТ_ОсновныеДанные.Номенклатура КАК Номенклатура,
    ВТ_ОсновныеДанные.СуммаПродаж КАК СуммаПродаж,
    ЕСТЬNULL(ДополнительныеСведения.Значение, "Не указано") КАК ДополнительноеСвойство
ИЗ
    ВТ_ОсновныеДанные КАК ВТ_ОсновныеДанные
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
        ПО ВТ_ОсновныеДанные.Контрагент = ДополнительныеСведения.Объект
        И ДополнительныеСведения.Свойство = &СвойствоКонтрагента

В данном примере мы применили функцию ЕСТЬNULL. Она позволяет сразу обработать ситуации, когда во второй таблице нет связанных данных, и заменить системное значение NULL на понятную пользователю пустую строку или значение по умолчанию. Такой подход полностью исключает «схлопывание» строк отчета.

Решение 3. Использование флага «Обязательная связь»

Если объединить запросы невозможно (например, один из наборов данных является внешним набором — таблицей значений, передаваемой из кода), обратите внимание на настройки связей наборов данных в СКД.

На вкладке «Связи наборов данных» для каждой связи предусмотрен флаг «Обязательная связь»:

Рекомендации по работе с собственными макетами

Если вы выводите новые поля в середину отчета, используя собственный макет шапки или группировки, всегда соблюдайте следующие правила:

  1. Связывайте параметры ячеек макета только с теми полями, которые объявлены в СКД как ресурсы. Это гарантирует, что система сможет рассчитать и вывести значение параметра в контексте любой строки, даже если детальная запись для этой строки отсутствует во втором наборе.
  2. В параметрах макета на вкладке «Макеты» проверяйте тип заполнения ячейки. Вместо типа Параметр вы можете использовать тип Текст со встроенными выражениями компоновки данных, чтобы более гибко обрабатывать пустые значения.
  3. Используйте выражения полей СКД для подмены пустых значений на уровне схемы. На вкладке «Наборы данных» в колонке «Выражение представления» для вашего поля можно написать понятную конструкцию: Представление(ЕСТЬNULL(ИмяПоля, "—")).

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

← На главную