Язык запросов 1С:Предприятие предоставляет разработчикам мощный инструмент для работы с данными — встроенные функции. Они позволяют не только агрегировать информацию, но и трансформировать её прямо в тексте запроса, экономя время на постобработке. Однако многие программисты ограничиваются стандартными СУММА() и КОЛИЧЕСТВО(), не используя весь потенциал доступных возможностей.
В этой статье мы разберём как применять функции в запросах 1С на практике: от базовых математических операций до работы с датами, строками и условной логикой. Вы узнаете, как комбинировать функции для решения нетривиальных задач, избегать типичных ошибок и оптимизировать производительность запросов. Все примеры приведены с учётом синтаксиса платформы 1С:Предприятие 8.3 и актуальны для последних версий конфигураций.
Базовые агрегатные функции: больше чем просто СУММА
Агрегатные функции — основа аналитики в запросах. Они позволяют сводить большие массивы данных к компактным показателям. Большинство разработчиков знают про СУММА(), но в арсенале платформы есть и другие полезные инструменты:
- 📊
МАКСИМУМ()/МИНИМУМ()— поиск экстремальных значений (например, самой поздней даты документа) - 🔢
СРЗНАЧ()— среднее арифметическое (полезно для анализа среднего чека или времени выполнения задач) - 🎯
КОЛИЧЕСТВО РАЗЛИЧНЫХ()— подсчёт уникальных значений (например, количество уникальных клиентов) - 📈
МЕДИАНА()— нахождение медианного значения (доступно с версии 8.3.14)
Пример использования нескольких агрегатов в одном запросе:
ВЫБРАТЬ
СУММА(Документ.СуммаДокумента) КАК ИтогоСумма,
КОЛИЧЕСТВО(Документ.Ссылка) КАК КоличествоДокументов,
МАКСИМУМ(Документ.Дата) КАК ПоследняяДата,
ССРЗНАЧ(Документ.СуммаДокумента) КАК СреднийЧек
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Важная особенность: агрегатные функции игнорируют значения NULL. Если вам нужно учитывать пустые значения (например, при подсчёте количества строк), используйте конструкцию КОЛИЧЕСТВО(ВЫРАЗИТЬ(Поле КАК Число(10,2))).
Функции работы с датами: от форматирования до арифметики
Работа с датами — одна из самых востребованных задач в бизнес-приложениях. Платформа 1С предоставляет богатый набор функций для манипуляций с временными значениями. Вот ключевые из них:
- 📅
НАЧАЛОПЕРИОДА()— приведение даты к началу дня/месяца/квартала/года - ⏳
ДОБАВИТЬКДАТЕ()— сдвиг даты на заданный интервал (дни, месяцы, годы) - 🔄
РАЗНОСТЬДАТ()— вычисление разницы между датами в заданных единицах - 📆
ДЕНЬНЕДЕЛИ()— определение дня недели (возвращает число от 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.
Пользовательские функции в запросах: когда стандартных не хватает
Иногда встроенных функций недостаточно для решения специфических задач. В таких случаях можно:
- Создать временную таблицу с предварительно рассчитанными значениями
- Использовать подзапросы для сложных вычислений
- Применить внешние функции через механизм расширений (доступно с версии 8.3.18)
Пример с временной таблицей для расчёта скользящего среднего:
ВЫБРАТЬ
Данные.Период,
Данные.Значение,
(ВЫБРАТЬ СРЗНАЧ(ВнутрДанные.Значение)
ИЗ &Данные КАК ВнутрДанные
ГДЕ ВнутрДанные.Период МЕЖДУ ДОБАВИТЬКДАТЕ(Данные.Период, МЕСЯЦ, -2) И Данные.Период) КАК СкользящееСреднее
ИЗ &Данные КАК Данные
Для часто используемых сложных выражений имеет смысл создать виртуальные таблицы в конфигурации или использовать предопределённые данные для хранения промежуточных результатов.
Оценить влияние на производительность|Проверить корректность работы с NULL|Учесть особенности транзакций|Документировать логику расчётов-->
Типичные ошибки и как их избегать
Даже опытные разработчики иногда допускают ошибки при работе с функциями в запросах. Вот наиболее распространённые проблемы:
- 🚫 Игнорирование NULL: Функции вроде
СУММА()корректно обрабатывают пустые значения, ноСРЗНАЧ()может давать неожиданные результаты при наличии NULL в данных - 🕒 Проблемы с временными зонами: Функции работы с датами не учитывают временные зоны пользователей
- 📏 Неявное приведение типов: Сравнение строк и чисел может приводить к неочевидным результатам
- 🔄 Рекурсивные ссылки: Вложенные подзапросы с функциями могут вызывать зацикливание
Пример проблемного запроса:
// ОШИБКА: Сравнение строки с числом
ВЫБРАТЬ Товары.Наименование
ИЗ Справочник.Номенклатура КАК Товары
ГДЕ Товары.Код = "001" // Код - числовое поле!
Исправленный вариант:
ВЫБРАТЬ Товары.Наименование
ИЗ Справочник.Номенклатура КАК Товары
ГДЕ Товары.Код = ЧИСЛО("001")
⚠️ Внимание: При использовании функций в условияхГДЕоптимизатор запросов может не использовать индексы. Для больших таблиц это критично влияет на производительность. В таких случаях лучше перенести фильтрацию в секциюГДЕбез функций или использовать временные таблицы.
Всегда тестируйте запросы с функциями на реальных объёмах данных — поведение может отличаться от работы с тестовыми наборами.
FAQ: Ответы на частые вопросы
Можно ли создать свою функцию для использования в запросах?
Прямо в тексте запроса — нет. Но можно:
- Создать функцию на встроенном языке и вызывать её через механизм расширений (с версии 8.3.18)
- Использовать временные таблицы с предварительно рассчитанными значениями
- Реализовать логику в виртуальных таблицах конфигурации
Для простых случаев часто хватает комбинации стандартных функций.
Почему функция СРЗНАЧ() возвращает неверное значение?
Наиболее вероятные причины:
- В выборке есть значения
NULL, которые игнорируются при расчёте среднего - Используется неявное приведение типов (например, суммируются строки вместо чисел)
- В группировке участвуют не все необходимые поля
Проверьте исходные данные с помощью запроса без агрегации.
Как в запросе получить текущую дату без параметров?
Используйте функцию ТЕКУЩАЯДАТА():
ВЫБРАТЬ
ТЕКУЩАЯДАТА() КАК Сегодня,
НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ) КАК НачалоМесяца
Обратите внимание, что эта дата вычисляется на сервере, а не на клиенте.
Можно ли в запросе использовать функции работы с массивами?
Нет, в языке запросов 1С нет функций для работы с массивами. Альтернативные подходы:
- Использовать временные таблицы для разворачивания массивов
- Применять строковые функции для работы с сериализованными данными
- Переносить обработку массивов на сторону встроенного языка
Как ускорить запрос с большим количеством функций?
Рекомендации по оптимизации:
- Перенесите часть вычислений во встроенный язык
- Используйте материализованные представления для часто используемых расчётов
- Разбейте сложный запрос на несколько простых с промежуточными временными таблицами
- Проверьте наличие индексов на полях, используемых в функциях
Анализируйте план выполнения запроса в консоли запросов.