Приведение типов в языке запросов 1С: когда без ВЫРАЗИТЬ не обойтись
Содержание
Оператор ВЫРАЗИТЬ(Выражение КАК Тип) в запросе 1С приводит значение поля к указанному типу: строку неограниченной длины — к строке фиксированной длины, составной тип — к одной ссылке, число — к числу нужной разрядности. Пример: ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент. Английский вариант того же оператора — CAST(... AS ...).
Выразить значение в запросе 1С нужно в трёх случаях. Первый — сравнить, сгруппировать или упорядочить поле неограниченной длины. Второй — обратиться к реквизиту составного поля без лишних соединений. Третий — округлить число или задать тип пустому полю во временной таблице. Преобразовать число в строку или строку в дату оператор не умеет: это главное, что нужно знать заранее.
Синтаксис ВЫРАЗИТЬ и типы, к которым можно привести
Общая форма:
ВЫРАЗИТЬ(<Выражение> КАК <Тип>)
Тип указывают так же, как в описании реквизитов метаданных:
| Тип | Как записать | Пример |
|---|---|---|
| Строка | СТРОКА(Длина) | ВЫРАЗИТЬ(Комментарий КАК СТРОКА(200)) |
| Число | ЧИСЛО(Длина, Точность) | ВЫРАЗИТЬ(Сумма КАК ЧИСЛО(15, 2)) |
| Дата | ДАТА | ВЫРАЗИТЬ(Значение КАК ДАТА) |
| Булево | БУЛЕВО | ВЫРАЗИТЬ(Значение КАК БУЛЕВО) |
| Ссылка | Справочник.Имя, Документ.Имя и т. д. | ВЫРАЗИТЬ(Субконто1 КАК Справочник.Контрагенты) |
Ключевое правило: ВЫРАЗИТЬ сужает или уточняет тип, но не конвертирует данные между примитивными типами. Строку можно привести только к строке, число — к числу, дату — к дате. Ссылку из составного поля — к одному из типов, которые в этом поле допустимы.
Имя типа пишется точно как в дереве метаданных, во множественном числе, если так назван объект: Справочник.Контрагенты, а не Справочник.Контрагент. Опечатка даёт синтаксическую ошибку запроса ещё до выполнения.
После закрывающей скобки можно сразу обращаться к реквизитам приведённой ссылки через точку. Конструктор запроса тоже умеет вставлять этот оператор: в редакторе выражения поля он есть в списке функций.
Строки неограниченной длины: сравнение, группировка, сортировка
Самый частый повод выразить строку в запросе 1С — реквизиты вроде Комментарий или Описание с длиной 0, то есть неограниченные. С ними СУБД работает как с большими текстовыми полями, и платформа запрещает их сравнивать, группировать и сортировать.
Попытка написать ГДЕ Документ.Комментарий = &Текст заканчивается ошибкой:
Нельзя сравнивать поля неограниченной длины и поля несовместимых типов
Решение — привести поле к строке фиксированной длины:
ВЫБРАТЬ
Реализация.Ссылка,
ВЫРАЗИТЬ(Реализация.Комментарий КАК СТРОКА(150)) КАК Комментарий
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
ВЫРАЗИТЬ(Реализация.Комментарий КАК СТРОКА(150)) = &Текст
Что происходит при приведении:
- ✂️ строка длиннее указанной обрезается до первых N символов;
- 🔍 сравнение идёт уже по обрезанному значению — две разные строки с одинаковым началом окажутся «равными»;
- 📊 по приведённому полю можно делать
СГРУППИРОВАТЬ ПО,УПОРЯДОЧИТЬ ПО,РАЗЛИЧНЫЕ.
В группировке выражение повторяют целиком:
ВЫБРАТЬ
ВЫРАЗИТЬ(Задачи.Описание КАК СТРОКА(100)) КАК Описание,
КОЛИЧЕСТВО(*) КАК Количество
ИЗ
Справочник.Задачи КАК Задачи
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(Задачи.Описание КАК СТРОКА(100))
Длину берите с запасом под реальные данные. Для поиска по началу текста подойдёт 50–100 символов, для точного совпадения — длина самого длинного значения, которое встречается в базе.
Для ПОДОБНО приводить поле не обязательно: условие Комментарий ПОДОБНО "%возврат%" работает и с неограниченной строкой. Приведение здесь только обрежет текст, и совпадение в конце длинного комментария потеряется.
Альтернатива — ПОДСТРОКА(Комментарий, 1, 150). Результат тот же, но ВЫРАЗИТЬ короче и явно показывает намерение.
Составные типы: Регистратор, Субконто, значения свойств
Поле составного типа хранит ссылку на один из нескольких объектов. Так устроены Регистратор у регистров, Субконто1..3 в бухгалтерских проводках, Значение у дополнительных реквизитов.
Если написать Регистратор.Дата или Субконто1.ИНН, платформа не знает, какую таблицу читать. Она соединяет поле со всеми таблицами из его состава. У регистра с тридцатью видами регистраторов это тридцать левых соединений в одном запросе.
ВЫРАЗИТЬ говорит платформе, какой тип ожидается:
ВЫБРАТЬ
Продажи.Регистратор,
ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
Здесь работают в паре два оператора:
- 🎯
ССЫЛКАотбирает строки, где в поле лежит ссылка нужного типа; - 🔗
ВЫРАЗИТЬдаёт доступ к реквизитам этого типа одним соединением.
Если в поле лежит ссылка другого типа, ВЫРАЗИТЬ вернёт NULL, а не ошибку. Поэтому условие ССЫЛКА нужно не для корректности, а чтобы не тащить в результат пустые строки.
Пример для бухгалтерского регистра — контрагент из первого субконто счёта 62:
ВЫБРАТЬ
ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Контрагенты) КАК Контрагент,
Остатки.СуммаОстатокДт
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, Счет В ИЕРАРХИИ (&Счет62), , ) КАК Остатки
Тот же приём нужен для значений дополнительных реквизитов: если известно, что свойство «Регион» хранит элемент справочника, приводите Значение к этому справочнику и берите .Наименование.
Соединения и ОБЪЕДИНИТЬ: приведение полей к общему типу
В условии соединения встречаются обе проблемы сразу: составное поле с одной стороны и строка неограниченной длины с другой.
Соединение по составному полю:
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, , , ) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Контрагенты) = Контрагенты.Ссылка
Соединение по неограниченной строке без приведения вызовет ту же ошибку о полях неограниченной длины. Приводить нужно обе стороны к одинаковой длине.
В запросах с ОБЪЕДИНИТЬ и во временных таблицах ВЫРАЗИТЬ задаёт тип полю, которое в одной из частей пустое. Типичный случай — первая часть объединения не содержит контрагента, вместо него NULL:
ВЫБРАТЬ
Поступление.Ссылка КАК Документ,
ВЫРАЗИТЬ(NULL КАК Справочник.Контрагенты) КАК Контрагент
ПОМЕСТИТЬ ВТ_Документы
ИЗ
Документ.ПоступлениеТоваровУслуг КАК Поступление
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Реализация.Ссылка,
Реализация.Контрагент
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
Зачем это делать:
- 📐 поле временной таблицы получает явный тип
Справочник.Контрагенты; - 🔗 через точку от него потом можно брать реквизиты без лишних соединений;
- 🗂 индекс по такому полю (
ИНДЕКСИРОВАТЬ ПО) строится по однотипным данным.
Вместо ВЫРАЗИТЬ(NULL КАК ...) для ссылок часто пишут ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка). Разница — в результате: первый вариант даёт NULL, второй — пустую ссылку. От этого зависит, как потом писать условия: ЕСТЬ NULL или = ЗНАЧЕНИЕ(...).
Даты и время: что ВЫРАЗИТЬ умеет и чего не умеет
Привести дату к строке вида «01.03.2026» средствами ВЫРАЗИТЬ нельзя. Отформатировать дату внутри запроса тоже нельзя. Оператор работает с датой только как с датой: например, вытаскивает её из составного поля.
ВЫРАЗИТЬ(ЗначенияСвойств.Значение КАК ДАТА)
Для всего остального в языке запросов есть отдельные функции:
| Задача | Функция |
|---|---|
| Обрезать время, взять начало дня/месяца | НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) |
| Взять конец периода | КОНЕЦПЕРИОДА(Дата, МЕСЯЦ) |
| Сдвинуть дату | ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 10) |
| Разница между датами | РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ) |
| Год, месяц, день как число | ГОД(Дата), МЕСЯЦ(Дата), ДЕНЬМЕСЯЦА(Дата) |
| Дата-константа | ДАТАВРЕМЯ(2026, 3, 1) |
Формат вывода задают там, где данные показывают: в настройках поля схемы компоновки (свойство «Формат») или в коде функцией Формат(Дата, "ДФ=dd.MM.yyyy").
Сравнивать дату со временем и дату без времени удобнее через НАЧАЛОПЕРИОДА(..., ДЕНЬ), а не через границы &Дата и &Дата + 86399. Но в ГДЕ по индексированному полю условие МЕЖДУ &Начало И &Конец быстрее, чем функция над полем.
Числа и точность вычислений
Для чисел ВЫРАЗИТЬ — штатный способ округлить результат прямо в запросе:
ВЫРАЗИТЬ(Товары.Сумма / Товары.Количество КАК ЧИСЛО(15, 2)) КАК Цена
Значение округляется до указанного числа знаков после запятой по арифметическим правилам. Пример: сумма 1000 при количестве 3 даёт 333,333…, после приведения — 333,33. Сумма 1000 при количестве 6 даёт 166,666…, после приведения — 166,67.
Правила, которые избавляют от копеечных расхождений:
- Приводите итог вычисления, а не промежуточные слагаемые.
ВЫРАЗИТЬ(А * Б / В КАК ЧИСЛО(15, 2))точнее, чем произведение уже округлённых значений. - Сначала умножайте, потом делите:
Сумма * 100 / Итогдаёт меньшую погрешность, чемСумма / Итог * 100. - Длину берите с запасом. Если значение не помещается в
ЧИСЛО(10, 2), запрос либо завершится ошибкой, либо вернёт неверный результат — зависит от СУБД. Для сумм обычно хватаетЧИСЛО(15, 2), для количества —ЧИСЛО(15, 3). - Чтобы получить целое, приводите к
ЧИСЛО(15, 0). Это округление, а не отбрасывание дробной части: 2,5 станет 3.
Деление на ноль в запросе — ошибка выполнения, ВЫРАЗИТЬ от неё не спасает. Защищайтесь условием:
ВЫБОР
КОГДА Товары.Количество = 0 ТОГДА 0
ИНАЧЕ ВЫРАЗИТЬ(Товары.Сумма / Товары.Количество КАК ЧИСЛО(15, 2))
КОНЕЦ КАК Цена
Числа в строку ВЫРАЗИТЬ не переводит: ВЫРАЗИТЬ(Сумма КАК СТРОКА(20)) запрос не примет. Склеивайте текст уже в коде или в макете отчёта.
NULL и пустые значения после приведения
NULL появляется после ВЫРАЗИТЬ в двух ситуациях:
- 🚫 в составном поле лежит ссылка другого типа, чем указан в операторе;
- 🕳 исходное значение уже было
NULL, например, из левого соединения.
Последствия легко пропустить. Условие ГДЕ ВЫРАЗИТЬ(Субконто1 КАК Справочник.Контрагенты).ИНН = &ИНН молча выкинет все строки, где в субконто лежит не контрагент. Обычно это нужный результат, но в отчёте по нескольким типам объектов строки пропадут.
Подставить значение вместо NULL помогает ЕСТЬNULL:
ЕСТЬNULL(ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент,
ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) КАК Контрагент
Для чисел пишут ЕСТЬNULL(ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)), 0). Без этого сумма с NULL в выражении Сумма1 + Сумма2 тоже станет NULL.
Проверить тип, а не результат приведения, можно функциями ТИПЗНАЧЕНИЯ(Поле) = ТИП(Справочник.Контрагенты) или оператором ССЫЛКА. Для разбора поля, где лежат ссылки разных типов, удобна конструкция ВЫБОР КОГДА Поле ССЫЛКА ... ТОГДА ВЫРАЗИТЬ(...) КОНЕЦ с отдельной веткой на каждый тип.
ВЫРАЗИТЬ и скорость запроса
На производительность оператор влияет в обе стороны.
Ускоряет — при обращении к реквизитам составных полей. Вместо соединения со всеми таблицами типа платформа делает одно соединение. На регистрах с десятками видов регистраторов разница заметна в разы, особенно в отчётах за год. Это главная причина, по которой опытные разработчики пишут ВЫРАЗИТЬ(Регистратор КАК ...) даже тогда, когда тип и так понятен из условия.
Замедляет — когда ВЫРАЗИТЬ стоит над полем в ГДЕ или в условии соединения:
| Где стоит ВЫРАЗИТЬ | Что происходит | Что делать |
|---|---|---|
Над неограниченной строкой в ГДЕ | Индекса по такому полю нет, СУБД читает всю таблицу | Отобрать строки по другим условиям, сравнение строк оставить последним |
Над составным полем в ПО | Индекс по полю может не использоваться | Сначала отобрать данные во временную таблицу с приведённым полем и проиндексировать её |
В выборке над ссылкой с .Реквизит | Одно соединение вместо многих | Оставить как есть: это правильное применение |
| Над числом в выборке | Затраты незаметны | Оставить |
Проверить, что изменилось, можно технологическим журналом или замером производительности: время запроса до и после правки на одинаковых данных даёт ответ быстрее теоретических рассуждений.
Права доступа на уровне записей (RLS) тоже добавляют соединения по составным полям. Если отчёт тормозит только у пользователей с ограниченными правами, ищите причину в шаблонах ограничений, а не в самом запросе.