При разработке отчетов на схеме компоновки данных (СКД) программисты часто сталкиваются с необходимостью тонкой настройки вывода строк и оформления таблиц. Типичная задача — исключить проведение расчетов по строкам, в которых ключевые показатели не заполнены, а также сделать так, чтобы вместо некрасивых нулей или пустых значений в отчете оставалась аккуратная пустая ячейка. При этом важно не перегружать СУБД тяжелыми и неоптимальными запросами с обилием условий.
В этой статье мы подробно разберем, как решить проблему обнуления строк в СКД, проанализируем, почему стандартный оператор ИЛИ замедляет работу системы, и рассмотрим профессиональные методы обхода этой проблемы. Также мы выясним, как правильно присваивать колонкам произвольные имена, содержащие цифры и спецсимволы (например, знак процента «%»).
Рассмотрим ситуацию, когда в исходных данных поле, по которому ведется расчет, может принимать значения NULL, Неопределено, быть равным нулю или пустой строке. Если мы попытаемся выполнить математические операции с такими значениями напрямую, то на выходе получим некорректный результат или заполненную нулями строку, которая визуально засоряет отчет.
Для того чтобы обойти эту проблему непосредственно в тексте запроса, мы можем использовать развернутое ветвление логики. Проанализируем пример кода, который решает эту задачу «в лоб»:
ВЫБОР
КОГДА СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = НЕОПРЕДЕЛЕНО
ИЛИ СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам ЕСТЬ NULL
ИЛИ СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = 0
ИЛИ СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = ""
ТОГДА 0
ИНАЧЕ "Расчет"
КОНЕЦ КАК ДоплатаШахтерам
Этот код успешно работает и решает задачу: если поле не заполнено или равно нулю, система вернет 0 (или пустую строку в зависимости от бизнес-логики), иначе будет произведен требуемый алгоритм расчета. Однако такое нагромождение условий делает запрос громоздким и трудночитаемым. Давайте разберем более изящные альтернативы, которые предоставляет нам платформа 1С.
Вместо длинного перечисления всех возможных видов «пустоты» мы можем использовать встроенную функцию языка запросов ЕСТЬNULL. Проанализируем, как работает эта функция: она проверяет первый параметр, и если его значение равно NULL, возвращает второй параметр (в нашем случае число 0).
Посмотрим, как сократится наше условие, если мы предварительно обработаем поле:
ВЫБОР
КОГДА ЕСТЬNULL(СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам, 0) = 0
ТОГДА 0
ИНАЧЕ "Расчет"
КОНЕЦ КАК ДоплатаШахтерам
Использование ЕСТЬNULL автоматически решает проблему отсутствующих связей в виртуальных или физических таблицах (когда СУБД возвращает NULL). Нам остается лишь сравнить полученный результат с нулем. Этот код значительно чище, проще в поддержке и работает быстрее.
Если данные по строке физически необходимы в запросе и должны участвовать в расчете общих итогов по отчету, но при этом на экране вместо нулей нужно отобразить пустые ячейки, лучшим решением будет использование механизма Условного оформления СКД. Это позволит нам не писать лишний код в запросе и сохранить чистоту архитектуры.
Разберем по шагам, как настроить визуальное сокрытие пустых строк:
ЧГ=0 или настройте параметр «Представление нуля» как пустую строку (пробел). Также можно использовать параметр «Текст», указав в его значении пустую строку, чтобы принудительно очистить ячейку при выполнении условий.ДоплатаШахтерам) и укажите вид сравнения «Равно», а в качестве значения укажите 0. Также можно добавить дополнительное условие на НЕОПРЕДЕЛЕНО или NULL, если эти типы данных могут пробиваться в результат.Этот способ является наиболее профессиональным, так как разделяет логику получения данных в запросе и логику их визуального представления на клиенте.
Если строки, в которых нет данных по доплатам, вообще не должны попадать в финальный отчёт, лучшим решением будет наложить фильтр прямо в настройках СКД. Нам не потребуется менять запрос.
Платформа 1С предоставляет мощный встроенный инструмент — вид сравнения «Заполнено» (и его противоположность — «Не заполнено»). Этот системный отбор на уровне платформы корректно обрабатывает все типы данных:
"".NULL и Неопределено.Просто добавьте в список отборов вашего отчета поле ПФРНаДоплатуШахтерам с видом сравнения «Заполнено». СКД самостоятельно модифицирует результирующий SQL-запрос, оптимизировав его под конкретную СУБД.
Выясним причину, почему опытные разработчики настоятельно рекомендуют избегать оператора ИЛИ в запросах 1С, особенно в секциях ГДЕ и в условиях соединения таблиц (ПО).
Когда СУБД (будь то Microsoft SQL Server, PostgreSQL или Oracle) строит план выполнения запроса, она пытается использовать заранее созданные индексы для ускорения поиска данных. Если в условии поиска присутствует оператор ИЛИ, связывающий разные поля или разнородные условия, оптимизатор СУБД зачастую не может построить эффективный план с использованием поиска по индексу (Index Seek). Вместо этого СУБД переходит к полному сканированию всей таблицы или индекса (Table Scan / Index Scan).
На небольших тестовых базах разница в скорости незаметна, но когда объем таблиц вырастает до сотен тысяч или миллионов записей, отчеты с конструкциями ИЛИ начинают вызывать серьезные задержки работы системы и приводить к избыточным блокировкам таблиц.
Существует несколько проверенных методологических подходов к замене неоптимального оператора ИЛИ.
Вариант А: Использование конструкции ИСТИНА В (...) в блоке ВЫБОР КОГДА
Если нам необходимо проверить одно и то же поле на соответствие списку различных значений в блоке выбора, то вместо громоздкого перечисления через ИЛИ лучше использовать следующую конструкцию:
ВЫБОР
КОГДА ИСТИНА В (
СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = НЕОПРЕДЕЛЕНО,
СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам ЕСТЬ NULL,
СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = 0,
СтраховыеВзносыПоФизическимЛицам.ПФРНаДоплатуШахтерам = ""
)
ТОГДА 0
ИНАЧЕ "Расчет"
КОНЕЦ КАК ДоплатаШахтерам
Такой синтаксис делает код приятным для чтения, избавляя от визуального шума. При этом СУБД обрабатывает такие конструкции более предсказуемо.
Вариант Б: Замена ИЛИ на ОБЪЕДИНИТЬ ВСЕ в секции ГДЕ
Если неоптимальное условие ИЛИ находится в секции фильтрации данных (например, нам нужно выбрать документы, где либо склад соответствует параметру, либо подразделение равно выбранному значению), то стандарты разработки 1С предписывают разбивать один тяжелый запрос на несколько простых, объединяя их результаты через оператор ОБЪЕДИНИТЬ ВСЕ.
Посмотрим на классический неоптимальный пример:
ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг
ГДЕ Склад = &Склад ИЛИ Подразделение = &Подразделение
А теперь проанализируем, как будет выглядеть оптимизированный вариант:
ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг ГДЕ Склад = &Склад
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг ГДЕ Подразделение = &Подразделение И НЕ (Склад = &Склад)
В оптимизированном варианте каждый из двух запросов будет выполняться СУБД независимо и использовать свой выделенный индекс по полям Склад и Подразделение. Скорость выполнения такого пакета на больших базах данных будет на порядки выше, чем у исходного запроса с оператором ИЛИ.
Еще одна частая проблема — необходимость назвать колонку в отчете понятным языком, например, «Доплата шахтерам 6%». Попытка прописать такой псевдоним непосредственно в тексте запроса через конструкцию КАК [Доплата шахтерам 6%] или в кавычках приведет к синтаксической ошибке.
Выясним, почему это происходит: по правилам платформы 1С, псевдонимы полей в тексте запроса должны соответствовать строгим правилам именования идентификаторов. Они не могут содержать пробелы, начинаться с цифр и включать любые специальные символы, кроме нижнего подчеркивания. Символ «%», скобки и пробелы находятся под строгим запретом.
Для решения этой проблемы мы можем использовать два штатных пути в рамках СКД.
Этот метод предпочтителен, так как заголовок зафиксируется в самой схеме компоновки и будет выводиться по умолчанию во всех новых вариантах отчета:
ДоплатаШахтерам).Доплата шахтерам 6%.При формировании отчета система автоматически подставит это значение в шапку таблицы, сохранив техническое имя поля для внутренних расчетов.
Если вам нужно переименовать поле только для определенного варианта отчета или в пользовательском режиме (без изменения конфигурации в конфигураторе):
Доплата шахтерам 6% и нажмите «ОК».Этот заголовок переопределит имя колонки для текущего варианта отчета. Этот метод также доступен продвинутым пользователям непосредственно в режиме «1С:Предприятие» при изменении настроек отчета.