Разработка и Конфигурация · 11 мин
ВЫРАЗИТЬ КАК ДАТА в запросе 1С: синтаксис, примеры и ошибки
Как применить ВЫРАЗИТЬ КАК ДАТА в запросе 1С: синтаксис, преобразование строки в дату, работа с составными типами, типичные ошибки и способы проверки результата.
Функция ВЫРАЗИТЬ в языке запросов 1С приводит значение поля к заданному типу. Когда речь идёт о дате, она решает две практические задачи: уточняет составной тип, чтобы запрос работал быстрее и корректно соединялся, и преобразует строковое представление даты в настоящий тип Дата, с которым можно сравнивать, группировать и вычислять разности.
Типичная ситуация: реквизит документа имеет составной тип (Дата и Строка, либо несколько видов документов), и при соединении таблиц платформа не может построить эффективный план запроса. Приведение через ВЫРАЗИТЬ(Поле КАК ДАТА) снимает неоднозначность и сообщает оптимизатору, с чем он работает. Другой частый случай — дата хранится в строковом реквизите (например, пришла из обмена или Excel), и её нужно превратить в полноценную дату для отбора по периоду.
Важно понимать ограничение: ВЫРАЗИТЬ не «чинит» любые строки. Если строка не соответствует формату даты, результатом будет пустая дата (01.01.0001), а не ошибка выполнения. Поэтому после преобразования результат всегда стоит проверять, особенно при обработке внешних данных.
Синтаксис ВЫРАЗИТЬ КАК ДАТА и базовый пример
Общая форма записи: ВЫРАЗИТЬ(Выражение КАК ДАТА). В качестве выражения может выступать поле таблицы, параметр, вложенный запрос или результат другой функции. В списке выбора результат обычно сразу получают псевдоним:
ВЫБРАТЬ
ВЫРАЗИТЬ(Документы.ПериодСтрокой КАК ДАТА) КАК ДатаДокумента
ИЗ
Документ.ПоступлениеТоваров КАК Документы
ГДЕ
ВЫРАЗИТЬ(Документы.ПериодСтрокой КАК ДАТА) >= &НачалоПериода
Тип ДАТА в запросе не принимает параметров точности — в отличие от ЧИСЛО или СТРОКА, где указываются длина и разрядность. Дата в 1С всегда хранится с точностью до секунды, и усечь её функцией ВЫРАЗИТЬ нельзя. Если нужно отбросить время, используют функции НАЧАЛОПЕРИОДА или КОНЕЦПЕРИОДА.
Обратите внимание: если поле уже имеет тип Дата, применение ВЫРАЗИТЬ к нему не даст никакого эффекта, но и не навредит. Лишние приведения типов в больших запросах лучше убирать — они затрудняют чтение и иногда мешают оптимизатору.
Уточнение составного типа поля
Составной тип — главный повод использовать ВЫРАЗИТЬ КАК ДАТА. Если реквизит объявлен как «Дата или Строка», то при соединении такой таблицы с другой по этому полю СУБД вынуждена учитывать оба типа, что резко увеличивает стоимость запроса. Приведение к одному типу позволяет использовать индексы и обычные планы выполнения.
ВЫБРАТЬ
ВЫРАЗИТЬ(Регистр.ПериодСоставной КАК ДАТА) КАК Период,
СУММА(Регистр.Сумма) КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Регистр
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(Регистр.ПериодСоставной КАК ДАТА)
Тот же приём работает в условиях соединения: ПО ВЫРАЗИТЬ(Таб1.Поле КАК ДАТА) = Таб2.Дата. Без приведения такое соединение по составному полю может вернуть неполный результат или выполняться на порядок медленнее на больших таблицах.
Практический признак того, что уточнение нужно: запрос с составным полем работает заметно медленнее аналогичного с однотипным, а в консоли запросов видно, что поле имеет несколько типов. Перед изменением запроса проверьте в конфигураторе фактический состав типов реквизита — иногда проще сузить тип в метаданных, чем приводить его в каждом запросе.
Преобразование строки в дату
Когда дата хранится в строковом реквизите, ВЫРАЗИТЬ пытается интерпретировать строку. Платформа корректно распознаёт строки в каноническом формате вида «ГГГГММДДччммсс» и ряд близких представлений, но поведение зависит от формата, поэтому полагаться на «автоугадывание» не стоит.
ВЫБРАТЬ
ВЫРАЗИТЬ(Данные.ДатаСтрокой КАК ДАТА) КАК ДатаЗначения
ИЗ
РегистрСведений.ЗагруженныеДанные КАК Данные
ГДЕ
ВЫРАЗИТЬ(Данные.ДатаСтрокой КАК ДАТА) <> ДАТАВРЕМЯ(1, 1, 1)
Условие <> ДАТАВРЕМЯ(1, 1, 1) отсекает строки, которые не удалось преобразовать. Это простой и надёжный способ отделить корректные данные от «мусора» при загрузках из внешних источников.
Если строка имеет формат «ДД.ММ.ГГГГ» и ВЫРАЗИТЬ её не распознаёт, придётся собирать дату из частей через ПОДСТРОКА и ДАТАВРЕМЯ. Это громоздко, поэтому правильное решение на уровне архитектуры — хранить даты в реквизитах типа Дата, а не Строка, и преобразовывать данные один раз при загрузке средствами встроенного языка.
ВЫРАЗИТЬ и ДАТАВРЕМЯ: когда что использовать
Эти две конструкции часто путают. ДАТАВРЕМЯ(год, месяц, день, час, минута, секунда) — литерал, создающий конкретное значение даты из чисел. ВЫРАЗИТЬ — приведение уже существующего значения. Они не взаимозаменяемы, но часто работают в паре: ВЫРАЗИТЬ готовит поле, ДАТАВРЕМЯ задаёт границу сравнения.
Для параметров запроса передавать значение типа Дата из кода предпочтительнее, чем собирать литерал ДАТАВРЕМЯ в тексте. Параметры безопаснее (исключают проблемы с форматами) и позволяют СУБД кэшировать план запроса. Литералы ДАТАВРЕМЯ уместны для фиксированных границ вроде пустой даты или технологических констант.
Сравнение подходов
Приведение существующего значения: уточнение составного типа, преобразование строки. Не создаёт дату из чисел
Литерал конкретной даты для сравнений и границ. Не применим к полям таблиц
Передача даты из кода через Запрос.УстановитьПараметр. Оптимален для отборов по периоду
Усечение даты-времени до начала периода. Используется вместе с ВЫРАЗИТЬ, а не вместо него
Работа с датой-временем и отсечение времени
Тип Дата в 1С включает время, и это источник классической ошибки: отбор Дата = &Дата не найдёт документы, если у параметра время 00:00:00, а у документов — фактическое время проведения. ВЫРАЗИТЬ эту проблему не решает, так как не усекает значение.
Правильный шаблон отбора за день выглядит так:
ГДЕ
Документ.Дата >= НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ)
И Документ.Дата <= КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)
Альтернатива — полуинтервал >= НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И < ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ), ДЕНЬ, 1). Оба варианта корректны; полуинтервал предпочтителен там, где важна точность до секунды и исключение пограничных совпадений.
Если приведённое через ВЫРАЗИТЬ поле нужно сгруппировать по дням, комбинируйте функции: НАЧАЛОПЕРИОДА(ВЫРАЗИТЬ(Поле КАК ДАТА), ДЕНЬ). Вложенность функций в запросах 1С допустима и не влияет на результат, но усложняет отладку — при проблемах выводите промежуточное значение отдельным полем.
- 1Определите фактический формат строки в данных: выведите несколько значений в консоли запросов
- 2Примените ВЫРАЗИТЬ(Поле КАК ДАТА) и добавьте в выборку исходное поле рядом для сравнения
- 3Найдите строки, где результат равен ДАТАВРЕМЯ(1,1,1), — это непреобразованные значения
- 4Если нераспознанных строк много, корректируйте данные при загрузке, а не в каждом запросе
- 5Только после очистки данных используйте поле в отборах и соединениях
Проверка результата и производительность
Контроль результата — обязательная часть работы с ВЫРАЗИТЬ. Минимальный набор проверок: количество пустых дат после приведения, сравнение количества строк до и после отбора, выборочная сверка исходных строк с преобразованными значениями. Для загруженных извне данных полезно один раз построить сводку по причинам неудачного преобразования.
По производительности: ВЫРАЗИТЬ в списке выбора почти бесплатна, но ВЫРАЗИТЬ в условии ГДЕ по неиндексированному выражению заставляет СУБД вычислять функцию для каждой строки. На больших таблицах выгоднее сначала поместить приведённые данные во временную таблицу, проиндексировать её и уже потом соединять и фильтровать.
Как проверить результат
Реальные даты, соответствующие исходным строкам
Массовые значения 01.01.0001 — строки не распознаны
Совпадает с ожидаемым объёмом после отбора
Резкое сокращение — условие отсекает валидные данные
Все ожидаемые пары найдены
Потери строк — типы в соединении всё ещё различаются
Сопоставимо с запросом по однотипному полю
Замедление в разы — приведение выполняется над всей таблицей без индекса
Ограничения и альтернативные решения
ВЫРАЗИТЬ КАК ДАТА не работает с NULL: если поле содержит NULL (например, после левого соединения), результат тоже будет NULL, а не пустая дата. Для замены NULL используйте ЕСТЬNULL: ЕСТЬNULL(ВЫРАЗИТЬ(Поле КАК ДАТА), ДАТАВРЕМЯ(1,1,1)).
В иерархических и разрезных сценариях помните, что в СКД приведение типов часто удобнее делать на уровне вычисляемых полей или ресурсов, а не в тексте запроса. А если единственная цель — получить дату без времени в отчёте, проще использовать периодичность регистра или функции периодов СКД, чем приведение типов.
Наконец, если составной тип в метаданных больше не нужен бизнес-логике, рассмотрите сужение типа реквизита в конфигураторе. Это устраняет проблему в корне: все запросы, отчёты и движения начинают работать с однотипным полем без ВЫРАЗИТЬ. Перед изменением типа обязательно проверьте существующие данные — значения несовместимых типов будут очищены при реструктуризации.
Что важно запомнить
ВЫРАЗИТЬ(Поле КАК ДАТА) уточняет составные типы и преобразует распознаваемые строки, но молча возвращает пустую дату для некорректных значений. Для отсечения времени применяйте НАЧАЛОПЕРИОДА, для границ — параметры или ДАТАВРЕМЯ, а результат преобразования всегда проверяйте отбором по пустой дате.
Частые вопросы
Почему ВЫРАЗИТЬ КАК ДАТА возвращает 01.01.0001?
Это пустая дата — результат неудачного преобразования. Строка не соответствует распознаваемому формату, либо поле содержит значение несовместимого типа. Найдите такие строки условием ВЫРАЗИТЬ(Поле КАК ДАТА) = ДАТАВРЕМЯ(1,1,1) и проверьте их исходное содержимое.
Можно ли указать формат даты в функции ВЫРАЗИТЬ?
Нет, язык запросов не позволяет задать формат преобразования. Если строка имеет нестандартный вид, преобразуйте её при загрузке средствами встроенного языка (функция Дата или разбор строки) и храните в реквизите типа Дата.
Как убрать время из даты в запросе?
Функцией НАЧАЛОПЕРИОДА: НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) вернёт дату с нулевым временем. ВЫРАЗИТЬ для этого не подходит — она меняет тип, а не усекает значение.
Чем отличается ВЫРАЗИТЬ КАК ДАТА от приведения в коде?
В запросе приведение выполняется на стороне СУБД над каждой строкой выборки. В коде функция работает с одним значением. Для одиночных значений и параметров используйте код, для массовой обработки полей таблиц — запрос.
Работает ли ВЫРАЗИТЬ КАК ДАТА с NULL?
Нет, NULL остаётся NULL. Чтобы заменить его пустой датой, оберните выражение в ЕСТЬNULL: ЕСТЬNULL(ВЫРАЗИТЬ(Поле КАК ДАТА), ДАТАВРЕМЯ(1,1,1)).
Влияет ли ВЫРАЗИТЬ на скорость запроса?
В списке полей — практически нет. В условиях и соединениях по большим таблицам — да: функция вычисляется для каждой строки и мешает использованию индексов. В таких случаях помещайте приведённые данные во временную таблицу с индексом.