Язык запросов 1С:Предприятие предоставляет разработчикам мощный инструмент для работы с данными — встроенные функции. Они позволяют не только агрегировать информацию, но и трансформировать её прямо в тексте запроса, экономя время на постобработке. Однако многие программисты ограничиваются стандартными СУММА() и КОЛИЧЕСТВО(), не используя весь потенциал доступных возможностей.

В этой статье мы разберём как применять функции в запросах 1С на практике: от базовых математических операций до работы с датами, строками и условной логикой. Вы узнаете, как комбинировать функции для решения нетривиальных задач, избегать типичных ошибок и оптимизировать производительность запросов. Все примеры приведены с учётом синтаксиса платформы 1С:Предприятие 8.3 и актуальны для последних версий конфигураций.

Базовые агрегатные функции: больше чем просто СУММА

Агрегатные функции — основа аналитики в запросах. Они позволяют сводить большие массивы данных к компактным показателям. Большинство разработчиков знают про СУММА(), но в арсенале платформы есть и другие полезные инструменты:

  • 📊 МАКСИМУМ() / МИНИМУМ() — поиск экстремальных значений (например, самой поздней даты документа)
  • 🔢 СРЗНАЧ() — среднее арифметическое (полезно для анализа среднего чека или времени выполнения задач)
  • 🎯 КОЛИЧЕСТВО РАЗЛИЧНЫХ() — подсчёт уникальных значений (например, количество уникальных клиентов)
  • 📈 МЕДИАНА() — нахождение медианного значения (доступно с версии 8.3.14)

Пример использования нескольких агрегатов в одном запросе:

ВЫБРАТЬ

СУММА(Документ.СуммаДокумента) КАК ИтогоСумма,

КОЛИЧЕСТВО(Документ.Ссылка) КАК КоличествоДокументов,

МАКСИМУМ(Документ.Дата) КАК ПоследняяДата,

ССРЗНАЧ(Документ.СуммаДокумента) КАК СреднийЧек

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Важная особенность: агрегатные функции игнорируют значения NULL. Если вам нужно учитывать пустые значения (например, при подсчёте количества строк), используйте конструкцию КОЛИЧЕСТВО(ВЫРАЗИТЬ(Поле КАК Число(10,2))).

📊 Какие агрегатные функции вы используете чаще всего?
СУММА
КОЛИЧЕСТВО
СРЗНАЧ
МАКСИМУМ/МИНИМУМ
Другие

Функции работы с датами: от форматирования до арифметики

Работа с датами — одна из самых востребованных задач в бизнес-приложениях. Платформа предоставляет богатый набор функций для манипуляций с временными значениями. Вот ключевые из них:

  • 📅 НАЧАЛОПЕРИОДА() — приведение даты к началу дня/месяца/квартала/года
  • ДОБАВИТЬКДАТЕ() — сдвиг даты на заданный интервал (дни, месяцы, годы)
  • 🔄 РАЗНОСТЬДАТ() — вычисление разницы между датами в заданных единицах
  • 📆 ДЕНЬНЕДЕЛИ() — определение дня недели (возвращает число от 1 до 7)

Практический пример: получение продаж по дням недели для анализа пиковых нагрузок:

ВЫБРАТЬ

ДЕНЬНЕДЕЛИ(Документ.Дата) КАК ДеньНедели,

СУММА(Документ.СуммаДокумента) КАК СуммаПродаж

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца

СГРУППИРОВАТЬ ПО

ДЕНЬНЕДЕЛИ(Документ.Дата)

УПОРЯДОЧИТЬ ПО

ДеньНедели

⚠️ Внимание: Функция РАЗНОСТЬДАТ() возвращает разницу в полных периодах. Например, разница между 1 января и 31 декабря того же года составит 0 лет, даже если прошёл почти полный год. Для точных расчётов используйте выражение с делением на количество дней в году.

Для форматирования дат в читаемый вид используйте функцию ФОРМАТ():

ВЫБРАТЬ

ФОРМАТ(Документ.Дата, "ДФ=dd.MM.yyyy; ДЛФ=ДД") КАК ДатаДокумента,

Документ.Номер

ИЗ

Документ.ЗаказПокупателя КАК Документ

Строковые функции: обработка текста прямо в запросе

Обработка текстовых данных часто требуется при формировании отчётов или подготовке данных для выгрузки. Вместо того чтобы делать это на клиенте, многие операции можно выполнить прямо в запросе:

ФункцияНазначениеПример использования
ЛЕВ()Возвращает заданное количество символов с начала строкиЛЕВ(Контрагент.Наименование, 10)
ПРАВ()Возвращает символы с конца строкиПРАВ(Документ.Номер, 4)
СРЕД()Извлекает подстроку из серединыСРЕД(Артикул, 4, 6)
НАЙТИ()Поиск подстроки (регистрозависимый)НАЙТИ("ООО", Контрагент.Наименование)
ЗАМЕНИТЬ()Замена подстроки на другуюЗАМЕНИТЬ(Адрес, "ул.", "улица")

Полезный приём: комбинирование строковых функций для нормализации данных. Например, приведение артикулов к единому формату:

ВЫБРАТЬ

ЗАМЕНИТЬ(

ЗАМЕНИТЬ(

ЗАМЕНИТЬ(Номенклатура.Артикул, " ", ""),

"-",

""

),

"_",

""

) КАК НормализованныйАртикул,

СУММА(Документ.Количество) КАК Количество

ИЗ...

💡

Для поиска без учёта регистра используйте конструкцию ВРЕГ(НАЙТИ("текст", Поле)) > 0 вместо прямого вызова НАЙТИ()

Условные выражения: CASE и ВЫБОР в запросах 1С

Логика ветвления в запросах реализуется через конструкцию ВЫБОР КОГДА...ТОГДА (аналог CASE WHEN в SQL). Это позволяет создавать сложные отчёты с динамической классификацией данных. Базовый синтаксис:

ВЫБОР

КОГДА Условие1 ТОГДА Значение1

КОГДА Условие2 ТОГДА Значение2

...

ИНАЧЕ ЗначениеПоУмолчанию

КОНЕЦ

Практический пример: группировка контрагентов по уровню оборотов:

ВЫБРАТЬ

Контрагент.Наименование,

СУММА(Документ.СуммаДокумента) КАК ОбщийОборот,

ВЫБОР

КОГДА СУММА(Документ.СуммаДокумента) > 1000000

ТОГДА "VIP-клиент"

КОГДА СУММА(Документ.СуммаДокумента) > 100000

ТОГДА "Крупный клиент"

ИНАЧЕ "Стандартный клиент"

КОНЕЦ КАК КатегорияКлиента

ИЗ...

Важное отличие от программного кода: в запросах нельзя использовать оператор ИЛИ внутри условия КОГДА. Вместо этого применяйте вложенные ВЫБОР или функцию ЕСТЬNULL() для обработки пустых значений.

Как ускорить запросы с множеством ВЫБОР?

Используйте предварительную группировку данных в подзапросах или временных таблицах. Сложная логика ВЫБОР в больших выборках может значительно замедлить выполнение.

Математические функции и работа с числами

Для финансовых расчётов и аналитики часто требуются математические операции. Платформа предоставляет стандартный набор функций:

  • ОКРУГЛ() — округление чисел с заданной точностью
  • ✖️ ОСТАТОК() — остаток от деления (модуль)
  • 📏 ЗНАК() — определение знака числа (-1, 0 или 1)
  • 🔢 МОДУЛЬ() — абсолютное значение числа
  • 📈 ЛОГ()/ЛОГ10() — логарифмы (для специализированных расчётов)

Типичная задача: расчёт скидок с округлением до копеек:

ВЫБРАТЬ

Номенклатура.Наименование,

Документ.Цена КАК ЦенаБезСкидки,

ОКРУГЛ(Документ.Цена * (1 - Документ.ПроцентСкидки/100), 2) КАК ЦенаСоСкидкой,

ОКРУГЛ(Документ.Цена * Документ.ПроцентСкидки/100, 2) КАК СуммаСкидки

ИЗ...

⚠️ Внимание: Функция ОКРУГЛ() использует банковское округление (к ближайшему чётному числу при половинных значениях). Это может давать неожиданные результаты при работе с валютами. Для бухгалтерского округления всегда указывайте явное количество знаков: ОКРУГЛ(Сумма, 2).

Особенность платформы 1С: при делении целых чисел результат автоматически округляется до целого. Чтобы получить дробный результат, хотя бы один из операндов должен быть явным числом с десятичной точкой: Сумма / 1.0 вместо Сумма / 1.

Пользовательские функции в запросах: когда стандартных не хватает

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

  1. Создать временную таблицу с предварительно рассчитанными значениями
  2. Использовать подзапросы для сложных вычислений
  3. Применить внешние функции через механизм расширений (доступно с версии 8.3.18)

Пример с временной таблицей для расчёта скользящего среднего:

ВЫБРАТЬ

Данные.Период,

Данные.Значение,

(ВЫБРАТЬ СРЗНАЧ(ВнутрДанные.Значение)

ИЗ &Данные КАК ВнутрДанные

ГДЕ ВнутрДанные.Период МЕЖДУ ДОБАВИТЬКДАТЕ(Данные.Период, МЕСЯЦ, -2) И Данные.Период) КАК СкользящееСреднее

ИЗ &Данные КАК Данные

Для часто используемых сложных выражений имеет смысл создать виртуальные таблицы в конфигурации или использовать предопределённые данные для хранения промежуточных результатов.

Оценить влияние на производительность|Проверить корректность работы с NULL|Учесть особенности транзакций|Документировать логику расчётов-->

Типичные ошибки и как их избегать

Даже опытные разработчики иногда допускают ошибки при работе с функциями в запросах. Вот наиболее распространённые проблемы:

  • 🚫 Игнорирование NULL: Функции вроде СУММА() корректно обрабатывают пустые значения, но СРЗНАЧ() может давать неожиданные результаты при наличии NULL в данных
  • 🕒 Проблемы с временными зонами: Функции работы с датами не учитывают временные зоны пользователей
  • 📏 Неявное приведение типов: Сравнение строк и чисел может приводить к неочевидным результатам
  • 🔄 Рекурсивные ссылки: Вложенные подзапросы с функциями могут вызывать зацикливание

Пример проблемного запроса:

// ОШИБКА: Сравнение строки с числом

ВЫБРАТЬ Товары.Наименование

ИЗ Справочник.Номенклатура КАК Товары

ГДЕ Товары.Код = "001" // Код - числовое поле!

Исправленный вариант:

ВЫБРАТЬ Товары.Наименование

ИЗ Справочник.Номенклатура КАК Товары

ГДЕ Товары.Код = ЧИСЛО("001")

⚠️ Внимание: При использовании функций в условиях ГДЕ оптимизатор запросов может не использовать индексы. Для больших таблиц это критично влияет на производительность. В таких случаях лучше перенести фильтрацию в секцию ГДЕ без функций или использовать временные таблицы.
💡

Всегда тестируйте запросы с функциями на реальных объёмах данных — поведение может отличаться от работы с тестовыми наборами.

FAQ: Ответы на частые вопросы

Можно ли создать свою функцию для использования в запросах?

Прямо в тексте запроса — нет. Но можно:

  1. Создать функцию на встроенном языке и вызывать её через механизм расширений (с версии 8.3.18)
  2. Использовать временные таблицы с предварительно рассчитанными значениями
  3. Реализовать логику в виртуальных таблицах конфигурации

Для простых случаев часто хватает комбинации стандартных функций.

Почему функция СРЗНАЧ() возвращает неверное значение?

Наиболее вероятные причины:

  • В выборке есть значения NULL, которые игнорируются при расчёте среднего
  • Используется неявное приведение типов (например, суммируются строки вместо чисел)
  • В группировке участвуют не все необходимые поля

Проверьте исходные данные с помощью запроса без агрегации.

Как в запросе получить текущую дату без параметров?

Используйте функцию ТЕКУЩАЯДАТА():

ВЫБРАТЬ

ТЕКУЩАЯДАТА() КАК Сегодня,

НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ) КАК НачалоМесяца

Обратите внимание, что эта дата вычисляется на сервере, а не на клиенте.

Можно ли в запросе использовать функции работы с массивами?

Нет, в языке запросов нет функций для работы с массивами. Альтернативные подходы:

  • Использовать временные таблицы для разворачивания массивов
  • Применять строковые функции для работы с сериализованными данными
  • Переносить обработку массивов на сторону встроенного языка
Как ускорить запрос с большим количеством функций?

Рекомендации по оптимизации:

  1. Перенесите часть вычислений во встроенный язык
  2. Используйте материализованные представления для часто используемых расчётов
  3. Разбейте сложный запрос на несколько простых с промежуточными временными таблицами
  4. Проверьте наличие индексов на полях, используемых в функциях

Анализируйте план выполнения запроса в консоли запросов.