Как писать вычисления, условия и приведение типов в языке запросов 1С

· 9 мин

Содержание

Выражение в запросе 1С — это всё, что стоит на месте поля: вычисление Количество * Цена, условие ВЫБОР КОГДА … КОНЕЦ, функция НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) или приведение типа ВЫРАЗИТЬ(Поле КАК Справочник.Номенклатура). Синтаксис одинаков в секциях ВЫБРАТЬ, ГДЕ, СГРУППИРОВАТЬ ПО, ИМЕЮЩИЕ и УПОРЯДОЧИТЬ ПО. Результату выражения почти всегда дают имя через КАК, иначе платформа назовёт колонку сама («Поле1»).

Вычислить можно двумя способами: прямо в запросе или потом в коде, обходя выборку. Запрос выигрывает, когда результат нужен для отбора, группировки или сортировки: СУБД сделает это быстрее цикла. Код удобнее, когда нужна сложная логика с вызовом функций общих модулей — язык запросов их не вызывает.

Операнды и арифметика: из чего собирается выражение

Операндом может быть поле таблицы, параметр &Параметр, литерал или результат другой функции.

📌 Литералы, которые встречаются чаще всего:

  • числа — 100, 0.2 (разделитель — точка);
  • строки — "Москва" в двойных кавычках;
  • даты — ДАТАВРЕМЯ(2025, 1, 1) или с временем ДАТАВРЕМЯ(2025, 1, 1, 23, 59, 59);
  • булево — ИСТИНА, ЛОЖЬ;
  • NULL и НЕОПРЕДЕЛЕНО;
  • предопределённые значения — ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Продажа), ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка).

Арифметических операций четыре: +, -, *, /. Умножение и деление выполняются раньше сложения и вычитания, скобки меняют порядок как в школе.

ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество * Товары.Цена КАК Сумма,
    Товары.Количество * Товары.Цена * 20 / 120 КАК НДСВключенный,
    (Товары.Цена - Товары.Себестоимость) * Товары.Количество КАК Наценка
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
    Товары.Ссылка = &Документ

Проверим на числах: 3 шт. по 1 200 руб. дают 3 600 руб., НДС внутри — 3 600 × 20 / 120 = 600 руб.

Любая арифметика с NULL даёт NULL. Если поле пришло из левого соединения и записи нет, Количество * Цена вернёт пустоту, а не ноль. Оборачивайте такие поля в ЕСТЬNULL(Поле, 0).

Имена таблиц и полей в примерах взяты из типовой конфигурации. В вашей базе сверяйте их через конструктор запроса: он показывает реальные реквизиты.

Строковые выражения: склейка, ПОДСТРОКА и поиск по шаблону

Строки склеивают плюсом: Контрагенты.Наименование + " (" + Контрагенты.ИНН + ")". Оба операнда должны быть строками.

ПОДСТРОКА

ПОДСТРОКА(Строка, Начало, Длина) вырезает кусок. Нумерация символов с единицы: ПОДСТРОКА("Накладная", 1, 4) вернёт «Накл».

У функции есть второе, практическое применение. Строки неограниченной длины (например, реквизит Комментарий) нельзя сравнивать, группировать и упорядочивать. ПОДСТРОКА(Комментарий, 1, 200) превращает такое поле в строку фиксированной длины, и с ним уже можно работать.

ПОДОБНО

Оператор ПОДОБНО проверяет строку по шаблону.

🔹 Спецсимволы шаблона:

  • % — любое количество любых символов;
  • _ — ровно один любой символ;
  • [абв] — один символ из перечисленных;
  • [^абв] — один символ, кроме перечисленных.
ГДЕ
    Номенклатура.Артикул ПОДОБНО "АБ-___"
    И Номенклатура.Наименование ПОДОБНО "%кабель%"

Чтобы искать сам символ процента или подчёркивания, укажите экранирующий знак через СПЕЦСИМВОЛ:

ГДЕ
    Номенклатура.Наименование ПОДОБНО "%50~%%" СПЕЦСИМВОЛ "~"

Шаблон найдёт «Скидка 50%», «50% предоплата» и подобные строки.

Функции для строк в новых платформах

В платформе 8.3.20 и новее в язык запросов добавили привычные строковые функции: ДЛИНАСТРОКИ, СТРНАЙТИ, СТРЗАМЕНИТЬ, ВРЕГ, НРЕГ, ЛЕВ, ПРАВ, СОКРЛ, СОКРП, СОКРЛП. Работают они так же, как одноимённые функции встроенного языка.

💡 Если база работает в режиме совместимости с более старой версией, эти функции в запросе вызовут синтаксическую ошибку. Режим совместимости виден в свойствах корня конфигурации в Конфигураторе.

Условия в запросе: ВЫБОР КОГДА и логические операторы

Конструкция ВЫБОР

Аналог Если … ИначеЕсли … КонецЕсли в запросе выглядит так:

ВЫБРАТЬ
    Остатки.Номенклатура,
    ВЫБОР
        КОГДА Остатки.КоличествоОстаток <= 0 ТОГДА "Нет в наличии"
        КОГДА Остатки.КоличествоОстаток < 10 ТОГДА "Заканчивается"
        ИНАЧЕ "В наличии"
    КОНЕЦ КАК Статус
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки

Условия проверяются сверху вниз, срабатывает первое истинное. Без ИНАЧЕ результат будет NULL, если ни одна ветка не подошла.

ВЫБОР годится не только в ВЫБРАТЬ. Его ставят внутрь агрегатной функции, в условие соединения и в УПОРЯДОЧИТЬ ПО — например, чтобы вывести наверх определённый склад.

Логические операторы

ОператорПримерЧто проверяет
И, ИЛИ, НЕСумма > 0 И НЕ ПометкаУдаленияКомбинация условий
МЕЖДУ … И …Дата МЕЖДУ &Начало И &КонецДиапазон включительно
В (…)Склад В (&СписокСкладов)Вхождение в список или подзапрос
В ИЕРАРХИИНоменклатура В ИЕРАРХИИ (&Группа)Элемент и все вложенные группы
ЕСТЬ NULLЦены.Цена ЕСТЬ NULLЗначение отсутствует
ССЫЛКАРегистратор ССЫЛКА Документ.ПоступлениеТоваровУслугТип ссылки

Сравнение Поле = NULL никогда не бывает истинным. Для проверки пустоты из соединения есть только ЕСТЬ NULL и НЕ … ЕСТЬ NULL.

Даты в запросе: периоды, сдвиги и разница

Работа с датой в запросе держится на четырёх функциях и наборе «извлекателей».

ФункцияПримерРезультат
НАЧАЛОПЕРИОДАНАЧАЛОПЕРИОДА(Дата, МЕСЯЦ)01.03.2025 00:00:00 для 17.03.2025
КОНЕЦПЕРИОДАКОНЕЦПЕРИОДА(Дата, ДЕНЬ)17.03.2025 23:59:59
ДОБАВИТЬКДАТЕДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 30)Дата плюс 30 дней
РАЗНОСТЬДАТРАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ)Дата2 минус Дата1 в днях

Основные периоды для первых трёх функций: ГОД, КВАРТАЛ, МЕСЯЦ, ДЕКАДА, НЕДЕЛЯ, ДЕНЬ, ЧАС, МИНУТА, у ДОБАВИТЬКДАТЕ есть ещё СЕКУНДА. В РАЗНОСТЬДАТ доступны СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД.

Пример: сколько дней прошло от отгрузки до даты отчёта.

ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    РАЗНОСТЬДАТ(Реализация.Дата, &ДатаОтчета, ДЕНЬ) КАК ДнейПрошло
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Проведен

Отгрузка 01.03, отчёт на 31.03 — в колонке будет 30.

Извлечь часть даты помогают ГОД(), КВАРТАЛ(), МЕСЯЦ(), ДЕНЬ(), ДЕНЬГОДА(), НЕДЕЛЯ(), ДЕНЬНЕДЕЛИ(), ЧАС(), МИНУТА(), СЕКУНДА(). ДЕНЬНЕДЕЛИ возвращает 1 для понедельника и 7 для воскресенья.

💡 Группировать продажи по месяцам удобнее через НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ), а не через МЕСЯЦ(Дата). Номер месяца склеит март 2024 и март 2025 в одну строку, а начало периода — нет.

Как выразить тип в запросе 1С: ВЫРАЗИТЬ, ССЫЛКА и ТИПЗНАЧЕНИЯ

Синтаксис ВЫРАЗИТЬ … КАК

ВЫРАЗИТЬ(Выражение КАК Тип) приводит значение к указанному типу. Типы бывают примитивные и ссылочные:

  • ВЫРАЗИТЬ(Комментарий КАК СТРОКА(150)) — обрезает строку неограниченной длины до 150 символов;
  • ВЫРАЗИТЬ(Сумма / Количество КАК ЧИСЛО(15, 2)) — оставляет два знака после запятой;
  • ВЫРАЗИТЬ(Субконто1 КАК Справочник.Контрагенты) — сужает составной тип до одного.

Если значение не приводится к типу, вместо ошибки вернётся NULL. Это удобно: ВЫРАЗИТЬ(Субконто1 КАК Справочник.Контрагенты) даст ссылку на контрагента, а для строк, где в субконто лежит договор или статья затрат, — NULL.

Главный приём: ВЫРАЗИТЬ для полей составного типа

Поле Регистратор у регистра может ссылаться на десятки видов документов. Запись Регистратор.Номер заставляет платформу соединить таблицу регистра со всеми этими документами. Запрос раздувается и тормозит.

Решение — сначала отобрать нужный тип, потом выразить поле:

ВЫБРАТЬ
    Движения.Регистратор КАК Документ,
    ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент
ИЗ
    РегистрНакопления.Продажи КАК Движения
ГДЕ
    Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Теперь соединение идёт с одной таблицей документов. На регистрах с миллионами записей разница в скорости бывает в разы. Тот же приём применяют к субконто, к реквизиту Объект в регистрах сведений и к любому полю с несколькими типами.

ТИПЗНАЧЕНИЯ и ТИП

ССЫЛКА проверяет тип ссылки, а для сравнения произвольных типов есть пара функций:

ГДЕ
    ТИПЗНАЧЕНИЯ(Хозрасчетный.Субконто1) = ТИП(Справочник.Номенклатура)

ТИП() принимает и примитивы: ТИП(ЧИСЛО), ТИП(СТРОКА), ТИП(ДАТА).

ПРЕДСТАВЛЕНИЕ и ПРЕДСТАВЛЕНИЕССЫЛКИ

ПРЕДСТАВЛЕНИЕ(Поле) возвращает текстовое представление значения. Для ссылок платформа добавляет такое поле при выводе в отчёт сама. Используйте функцию в итоговой выборке, а не в условиях ГДЕ: сравнивать по представлению медленно и ненадёжно.

Агрегатные функции и выражения при группировке

Функций шесть:

ФункцияЧто считает
СУММА(Поле)Сумму, NULL пропускает
КОЛИЧЕСТВО(Поле)Число строк, где поле не NULL
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле)Число уникальных значений
КОЛИЧЕСТВО(*)Все строки
МАКСИМУМ, МИНИМУМНаибольшее и наименьшее
СРЕДНЕЕ(Поле)Среднее по непустым значениям

Внутрь агрегата можно поставить любое выражение. Так считают условные суммы в одной строке:

ВЫБРАТЬ
    Продажи.Контрагент КАК Контрагент,
    СУММА(Продажи.Сумма) КАК Всего,
    СУММА(ВЫБОР
            КОГДА Продажи.Период >= &НачалоМесяца ТОГДА Продажи.Сумма
            ИНАЧЕ 0
        КОНЕЦ) КАК ЗаТекущийМесяц,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Регистратор) КАК ЧислоДокументов
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Период МЕЖДУ &НачалоГода И &КонецПериода
СГРУППИРОВАТЬ ПО
    Продажи.Контрагент
ИМЕЮЩИЕ
    СУММА(Продажи.Сумма) > 100000

🔸 Правила, которые проверяет платформа:

  • каждое поле в ВЫБРАТЬ либо стоит под агрегатной функцией, либо перечислено в СГРУППИРОВАТЬ ПО;
  • группировать можно по выражению: СГРУППИРОВАТЬ ПО НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) — в выборке тогда пишут то же выражение;
  • условие на исходные строки ставят в ГДЕ, условие на итог группы — в ИМЕЮЩИЕ.

Средняя цена через СРЕДНЕЕ(Цена) считает среднее арифметическое строк, без учёта объёма. Средневзвешенная цена — это СУММА(Сумма) / СУММА(Количество), и её нужно защитить от деления на ноль (ниже).

Выражения в СКД: что работает иначе

Текст запроса в схеме компоновки данных пишется на том же языке, со всеми функциями из разделов выше. Отличаются поля, которые задают на вкладках схемы.

🔹 Где в СКД встречаются выражения:

  • вычисляемые поля — формула от полей набора, например Сумма - Себестоимость;
  • ресурсы — выражение итога, например Сумма(Сумма) или Сумма(Сумма) / Сумма(Количество);
  • условное оформление и отборы — условия по полям.

Язык выражений СКД похож на язык запросов, но не совпадает с ним. В нём можно вызывать экспортные функции общих модулей, есть функция ВычислитьВыражение для расчётов по группировкам. Вычисляемые поля считаются уже после выполнения запроса, поэтому отбор по ним не ускоряет выборку из базы.

💡 Если поле нужно для отбора или группировки на больших объёмах, рассчитайте его в тексте запроса набора данных, а не вычисляемым полем.

Частые ошибки в выражениях и медленные конструкции

Ошибки, которые останавливают запрос

  • ❌ Поле не входит в группу — поле есть в ВЫБРАТЬ, но его нет в СГРУППИРОВАТЬ ПО и оно не под агрегатом. Добавьте поле в группировку или оберните в МАКСИМУМ.
  • ❌ Деление на ноль. СУБД прерывает запрос. Делитель проверяют заранее:
ВЫБОР
    КОГДА СУММА(Продажи.Количество) = 0 ТОГДА 0
    ИНАЧЕ СУММА(Продажи.Сумма) / СУММА(Продажи.Количество)
КОНЕЦ КАК СредняяЦена
  • ❌ Сравнение строки неограниченной длины. Платформа не даёт сравнивать и группировать такие поля — приведите их через ВЫРАЗИТЬ(… КАК СТРОКА(N)) или ПОДСТРОКА.
  • ❌ NULL вместо числа. Итог по левому соединению пустой, потому что одна из колонок NULL. Лечится ЕСТЬNULL.

Выражения, которые убивают скорость

КонструкцияПочему медленноКак переписать
НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) = &День в ГДЕФункция над полем мешает СУБД использовать индексДата МЕЖДУ &НачалоДня И &КонецДня
Наименование ПОДОБНО "%текст%"Ведущий % требует просмотра всей таблицыШаблон с началом строки "текст%", если подходит по смыслу
Регистратор.Дата у составного поляСоединение со всеми типами документовССЫЛКА в условии + ВЫРАЗИТЬ
Отбор в ГДЕ по виртуальной таблицеТаблица сначала собирается целикомУсловие в параметрах таблицы: Остатки(&Дата, Склад = &Склад)
Длинная цепочка ИЛИ по разным полямИндекс часто не используетсяОБЪЕДИНИТЬ ВСЕ двух запросов или временная таблица

Тяжёлое выражение, которое нужно в нескольких местах, выгоднее посчитать один раз во временной таблице (ПОМЕСТИТЬ ВТ_Данные) и дальше обращаться к готовому полю.

Проверьте себя
Что вернёт ВЫРАЗИТЬ(Субконто1 КАК Справочник.Контрагенты), если в субконто лежит договор?
Чем проверить, что поле из левого соединения пустое?
Как сгруппировать продажи по месяцам, не смешивая разные годы?

Частые вопросы

Можно ли вызвать функцию общего модуля в тексте запроса?
Нет. Запрос выполняет СУБД, она не знает о коде конфигурации. Посчитайте значение в коде и передайте его параметром или используйте вычисляемое поле СКД.
Чем ЕСТЬNULL отличается от ЕСТЬ NULL?
ЕСТЬNULL(Поле, 0) — функция замены: возвращает второй аргумент, если первый пустой. Поле ЕСТЬ NULL — логическое условие, возвращает ИСТИНА или ЛОЖЬ.
Как в запросе округлить число до копеек?
Приведите результат к числу с двумя знаками: ВЫРАЗИТЬ(Сумма * 1.2 КАК ЧИСЛО(15, 2)). Первое число — общая длина, второе — знаки после запятой.
Как подставить в запрос значение перечисления?
Через ЗНАЧЕНИЕ(Перечисление.ИмяПеречисления.ИмяЗначения) прямо в тексте или параметром. Для пустой ссылки — ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).
Где проверить выражение, не запуская отчёт?
В консоли запросов: она выполняет текст и показывает результат. В Конфигураторе конструктор запроса проверяет синтаксис при нажатии ОК.