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