При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с неприятной особенностью: при попытке расшифровать (сделать drill-down) конкретную ячейку, вместо ожидаемого списка детальных записей отчет выводит абсолютно все строки, игнорируя фильтр расшифровки. Особенно часто это проявляется в отчетах, где используется левое соединение (LEFT JOIN) и обработка пустых значений через ЕСТЬNULL. В данной статье мы подробно разберем причины такого поведения и рассмотрим несколько способов решения этой проблемы.
Рассмотрим типичную ситуацию. У нас есть основной набор данных (например, список сотрудников) и мы присоединяем к нему данные из регистра сведений (например, заметки или дополнительные свойства) с помощью левого соединения. Для красоты вывода мы преобразуем неопределенные значения (NULL) в читаемый текст, например, "Отсутствие записи". В тексте запроса это выглядит примерно так:
ВЫБРАТЬ
Работники.Сотрудник,
ВЫРАЗИТЬ(ЕСТЬNULL(втЗаметки.Содержание, "Отсутствие записи") КАК СТРОКА(50)) КАК Содержание
ИЗ
ВТ_КадровыеДанные КАК Работники
ЛЕВОЕ СОЕДИНЕНИЕ втАктуальныеЗаметки КАК втЗаметки
ПО Работники.Физлицо = втЗаметки.Объект
Проблема заключается в том, как механизм расшифровки 1С генерирует фоновый запрос. Когда вы нажимаете на ячейку со значением "Отсутствие записи", СКД пытается применить фильтр ГДЕ Содержание = "Отсутствие записи" к исходному запросу.
Выясним причину ошибки: Значение "Отсутствие записи" является виртуальным, оно не существует в физических таблицах базы данных. Оптимизатор запросов СКД при попытке расшифровки часто не может корректно пробросить это условие через левое соединение во временные таблицы. Не найдя способа применить фильтр к реальным данным, система может просто отбросить его, что и приводит к выводу всех записей отчета без фильтрации.
Один из надежных, хотя и трудоемких способов — переписать запрос таким образом, чтобы избавиться от левого соединения, при котором возникают NULL значения, заменяемые текстом. Мы можем разделить получение данных на две части и объединить их. Рассмотрим этот алгоритм подробнее:
INNER JOIN).NULL в правой таблице.Пример реализации такого запроса:
ВЫБРАТЬ
ВТ_КадровыеДанные.Сотрудник,
ВТ_КадровыеДанные.Физлицо,
ВЫРАЗИТЬ(втАктуальныеЗаметки.Содержание КАК СТРОКА(50)) КАК Содержание
ИЗ
ВТ_КадровыеДанные КАК ВТ_КадровыеДанные
ВНУТРЕННЕЕ СОЕДИНЕНИЕ втАктуальныеЗаметки КАК втАктуальныеЗаметки
ПО ВТ_КадровыеДанные.Физлицо = втАктуальныеЗаметки.Объект
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ВТ_КадровыеДанные.Сотрудник,
ВТ_КадровыеДанные.Физлицо,
"Отсутствие записи"
ИЗ
ВТ_КадровыеДанные КАК ВТ_КадровыеДанные
ЛЕВОЕ СОЕДИНЕНИЕ втАктуальныеЗаметки КАК втАктуальныеЗаметки
ПО ВТ_КадровыеДанные.Физлицо = втАктуальныеЗаметки.Объект
ГДЕ
втАктуальныеЗаметки.Объект ЕСТЬ NULL
В этом случае при расшифровке строки "Отсутствие записи" СКД будет работать со второй частью объединения, где это значение прописано явно, и фильтрация отработает корректно.
Это более элегантный способ, который позволяет оставить запрос простым. Мы переносим логику замены NULL из SQL-запроса в саму схему компоновки данных. Проанализируем шаги:
ЕСТЬNULL. В результате в поле Содержание будут приходить либо реальные строки, либо NULL.СодержаниеПредставление) и в колонке "Выражение" напишем: ЕстьNULL(Содержание, "Отсутствие записи").Содержание на наше вычисляемое поле.Почему это работает: При такой настройке СКД понимает структуру данных. При расшифровке система будет накладывать фильтр на исходное поле Содержание с условием НЕ ЗАПОЛНЕНО (или проверкой на NULL), что является стандартной операцией для платформы и не вызывает сбоев оптимизатора.
Если нам важно, чтобы фильтрация при расшифровке шла по пустому значению, но пользователь видел красивый текст, мы можем воспользоваться механизмом представлений полей набора данных:
Содержание.Выбор Когда Содержание Есть NULL Тогда "Отсутствие записи" Иначе Содержание Конец.В этом случае "Путь к данным" по-прежнему указывает на поле, которое может быть NULL, а визуальный текст подменяется только в момент вывода в ячейку. Расшифровка при этом будет ориентироваться на значение NULL, и фильтр применится правильно.
Рассмотрим еще несколько важных моментов, которые влияют на корректность расшифровки в сложных отчетах:
ВЫРАЗИТЬ(... КАК СТРОКА(N)) в запросе, 1С иногда может некорректно сравнивать строки из-за разного количества пробелов (особенно в полях фиксированной длины CHAR). Старайтесь использовать вычисляемые поля для преобразования типов, если это возможно.Таким образом, мы выяснили, что проблема расшифровки чаще всего кроется в попытке СКД отфильтровать данные по "виртуальному" значению, созданному внутри запроса. Используя вычисляемые поля или выражения представления, вы сохраните чистоту кода и обеспечите пользователям корректную работу с отчетами.