Запросы в 1С:Предприятие — это мощный инструмент для извлечения, обработки и анализа данных из базы. Они позволяют получать информацию из справочников, документов, регистров и других объектов конфигурации без необходимости писать сложные циклы на встроенном языке. Понимание механизма работы запросов критично для разработчиков, администраторов и даже опытных пользователей, которые хотят автоматизировать отчеты или аналитику.

В отличие от традиционных SQL-запросов, синтаксис 1С-запросов имеет свои особенности: он адаптирован под специфику платформы, поддерживает работу с иерархическими данными и интегрирован с системой типов . Однако многие принципы (например, соединения таблиц или агрегатные функции) остаются схожими. В этой статье мы разберем, как устроены запросы"под капотом", какие бывают виды конструкций, и как избежать типичных ошибок при их написании.

1. Архитектура запросов в 1С: как они выполняются

Когда вы пишете запрос в , платформа преобразует его в набор операций над виртуальными таблицами — специальными представлениями данных, которые формируются на основе объектов конфигурации (справочников, документов, регистров и т.д.). Важно понимать, что запросы не работают напрямую с физической базой данных (будь то Microsoft SQL Server, PostgreSQL или файловая база). Вместо этого они оперируют абстракцией, которую предоставляет платформа.

Процесс выполнения запроса можно условно разделить на три этапа:

  • 🔹 Парсинг и валидация — платформа проверяет синтаксис запроса, наличие используемых объектов в конфигурации и права доступа.
  • 🔹 Оптимизация плана выполнения — система анализирует, как эффективнее получить данные (например, использовать индексы или кэш).
  • 🔹 Исполнение и возвращение результата — формируется временная таблица с данными, которая передается в код на встроенном языке.

Один из ключевых моментов: может кэшировать результаты запросов, если их структура и параметры не изменились. Это значительно ускоряет повторные обращения, но требует осторожности при работе с динамическими данными (например, в транзакциях).

📊 Как часто вы используете запросы в 1С?
Ежедневно
Несколько раз в неделю
Редко, только для отчетов
Никогда не писал сам

2. Базовый синтаксис: структура запроса и ключевые конструкции

Минимальный запрос в состоит из двух обязательных частей: указания источников данных (таблиц) и списка полей, которые нужно получить. Например:

ВЫБРАТЬ

Справочник.Номенклатура.Наименование КАК Наименование,

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

ИЗ

Справочник.Номенклатура КАК Справочник_Номенклатура

Основные конструкции, которые используются в запросах:

  • 📌 ВЫБРАТЬ — указывает поля для выборки (аналог SELECT в SQL).
  • 📌 ИЗ — определяет источники данных (аналог FROM).
  • 📌 ГДЕ — фильтрация данных по условиям (аналог WHERE).
  • 📌 УПОРЯДОЧИТЬ ПО — сортировка результатов (аналог ORDER BY).
  • 📌 ГРУППИРОВКА ПО — агрегация данных (аналог GROUP BY).

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

💡

Используйте псевдонимы (алиасы) для таблиц и полей с ключевым словом КАК — это сделает запрос читабельнее и защитит от ошибок при изменении имен объектов в конфигурации.

3. Типы соединений таблиц и их влияние на производительность

В запросах поддерживаются те же типы соединений, что и в SQL: внутренние (ВНУТРЕННЕЕ СОЕДИНЕНИЕ), левые (ЛЕВОЕ СОЕДИНЕНИЕ), правые и полные. Однако их реализация имеет нюансы из-за особенностей платформы.

Рассмотрим разницу на примере соединения справочника Номенклатура и документа ПоступлениеТоваров:

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

Важный момент: левые соединения могут значительно замедлить запрос, если правая таблица содержит большое количество записей. Например, соединение документа РеализацияТоваров с регистром ОстаткиТоваров по полю Номенклатура без дополнительных фильтров приведет к полному сканированию регистра.

💡

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

4. Агрегатные функции и группировка данных

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

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

ВЫБРАТЬ

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

СУММА(Документ.РеализацияТоваров.Количество) КАК ОбщееКоличество,

СУММА(Документ.РеализацияТоваров.СуммаДокумента) КАК ОбщаяСумма

ИЗ

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

ГДЕ

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

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

Документ.РеализацияТоваров.Номенклатура

Обратите внимание на параметры &НачалоПериода и &КонецПериода — это параметры запроса, которые можно передавать из кода на встроенном языке. Их использование делает запрос гибким и переиспользуемым.

Частые ошибки при группировке:

  • ❌ Забывают добавить неагрегируемые поля в ГРУППИРОВКА ПО (приводит к ошибке выполнения).
  • ❌ Используют КОЛИЧЕСТВО(*) вместо КОЛИЧЕСТВО(Поле), что может давать неожиданные результаты при наличии NULL.
  • ❌ Не фильтруют данные перед группировкой, что приводит к избыточным вычислениям.
Что такое"перекрестное соединение" в 1С?

В 1С нет явного оператора CROSS JOIN, но его эффект можно получить, если указать несколько источников в секции ИЗ без условия соединения. Например:

ВЫБРАТЬ

Справочник.Номенклатура.Наименование КАК Номенклатура,

Справочник.Контрагенты.Наименование КАК Контрагент

ИЗ

Справочник.Номенклатура КАК Справочник_Номенклатура,

Справочник.Контрагенты КАК Справочник_Контрагенты

Такой запрос вернет декартово произведение двух справочников (все возможные комбинации строк), что крайне редко бывает полезно на практике и обычно является ошибкой.

5. Подзапросы и временные таблицы: когда и как использовать

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

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

Номенклатура.Артикул В (

ВЫБРАТЬ

ПоступлениеТоваров.Номенклатура.Артикул

ИЗ

Документ.ПоступлениеТоваров КАК ПоступлениеТоваров

ГДЕ

ПоступлениеТоваров.Дата > &ДатаНачала

)

Временные таблицы — это механизм для хранения промежуточных результатов внутри одного запроса. Они создаются с помощью конструкции ПОМЕСТИТЬ... ВО ВРЕМЕННУЮ ТАБЛИЦУ и могут использоваться для:

  • 🔄 Упрощения сложных запросов (разбиение на логические блоки).
  • 🔄 Повторного использования одних и тех же данных без дублирования кода.
  • 🔄 Оптимизации производительности (платформа может кэшировать временные таблицы).

Пример с временной таблицей:

ВЫБРАТЬ

Поступление.Номенклатура КАК Номенклатура,

СУММА(Поступление.Количество) КАК Поступило

ПОМЕСТИТЬ ПоступленияЗаПериод

ИЗ

Документ.ПоступлениеТоваров КАК Поступление

ГДЕ

Поступление.Дата МЕЖДУ &Начало И &Конец

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

Поступление.Номенклатура

//////////////////////////////////////////////////////////////

ВЫБРАТЬ

ПоступленияЗаПериод.Номенклатура КАК Номенклатура,

ПоступленияЗаПериод.Поступило,

ПродажиЗаПериод.Продано

ИЗ

ПоступленияЗаПериод КАК ПоступленияЗаПериод

ЛЕВОЕ СОЕДИНЕНИЕ ВРЕМЕННАЯ ТАБЛИЦА ПродажиЗаПериод КАК ПродажиЗаПериод

ПО ПоступленияЗаПериод.Номенклатура = ПродажиЗаПериод.Номенклатура

🔲 Убедитесь, что временная таблица действительно нужна (нельзя ли обойтись подзапросом?)

🔲 Проверьте, что имена временных таблиц уникальны в пределах запроса

🔲 Не создавайте временные таблицы с большим объемом данных без необходимости

🔲 Используйте индексируемые поля для соединений с временными таблицами

-->

6. Оптимизация запросов: как ускорить выполнение

Медленные запросы — одна из самых распространенных проблем в , особенно в крупных базах с миллионами записей. Основные причины тормозов:

  • 🐢 Отсутствие фильтров по датам или другим индексируемым полям.
  • 🐢 Чрезмерное использование ЛЕВОЕ СОЕДИНЕНИЕ без ограничений.
  • 🐢 Выборка ненужных полей (например, ВЫБРАТЬ *).
  • 🐢 Сложные вычисления в секции ВЫБРАТЬ (лучше перенести их в код на встроенном языке).

Практические советы по оптимизации:

  1. Всегда фильтруйте данные по датам, организациям или другим реквизитам, которые имеют индексы.
  2. Используйте РАЗЛИЧНЫЕ для исключения дублей, если они не нужны.
  3. Избегайте функций над полями в условиях (например, ГДЕ ЛЕВ(Наименование, 3) ="АБВ" — это блокирует использование индексов).
  4. Для больших выборок используйте ПАКЕТНЫЙ РЕЖИМ или ПОМЕСТИТЬ В МАССИВ.

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

ВЫБРАТЬ РАЗЛИЧНЫЕ

Документ.Ссылка КАК Ссылка,

Документ.Дата КАК Дата,

Документ.СуммаДокумента КАК Сумма

ИЗ

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

ГДЕ

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

И Документ.Организация = &ТекущаяОрганизация

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

Документ.Дата

💡

Используйте инструмент"План запроса" в конфигураторе (меню Администрирование → Тестирование и исправление → План запроса), чтобы анализировать, как платформа выполняет ваш запрос и где возникают"узкие места".

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

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

⚠️ Внимание: Если в запросе используется виртуальная таблица регистра срезом последних, убедитесь, что дата в параметре НаДату не превышает текущую дату базы. Иначе запрос вернет пустой результат, так как данные еще не сформированы.

Ошибки и способы их исправления:

Ошибка Причина Как исправить
"Поле не найдено" Опечатка в имени поля или объекта Проверьте регистр и синтаксис (например, Номенклатура.Наименование, а не Наименование)
"Недопустимое использование агрегатной функции" Агрегатная функция (например, СУММА) используется без ГРУППИРОВКА ПО Добавьте группировку или уберите агрегатную функцию
Запрос выполняется слишком долго Отсутствуют фильтры по индексируемым полям Добавьте условия по дате, организации или другим реквизитам с индексами
"Типы не совпадают" Попытка сравнить поля разных типов (например, строку и число) Используйте явное приведение типов (например, ЧИСЛО(Поле))

Еще одна распространенная проблема — некорректная работа с параметрами. Например, если параметр не инициализирован или имеет неверный тип, запрос может вернуть неожиданные результаты. Всегда проверяйте значения параметров перед выполнением запроса:

Если НЕ ЗначениеЗаполнено(НачалоПериода) Тогда

НачалоПериода = НачалоДня(ТекущаяДата);

КонецЕсли;

8. Практическое применение: примеры запросов для задач

Рассмотрим несколько реальных примеров запросов, которые часто требуются в работе:

1. Выборка документов с детализацией по строкам табличной части:

ВЫБРАТЬ

Документ.Ссылка КАК Документ,

Документ.Дата КАК Дата,

Документ.Товары.Номенклатура КАК Номенклатура,

Документ.Товары.Количество КАК Количество,

Документ.Товары.Цена КАК Цена,

Документ.Товары.Сумма КАК СуммаСтроки

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваров.Товары КАК Документ_Товары

ПО Документ.Ссылка = Документ_Товары.Ссылка

ГДЕ

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

2. Поиск дублей в справочнике по нескольким полям:

ВЫБРАТЬ

Наименование,

Артикул,

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

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

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

Наименование,

Артикул

ИМЕЮЩИЕ

КОЛИЧЕСТВО(*) > 1

3. Расчет остатков товара на дату с учетом движений:

ВЫБРАТЬ

ОстаткиТоваров.Номенклатура КАК Номенклатура,

ОстаткиТоваров.КоличествоОстаток КАК Остаток

ИЗ

РегистрНакопления.ОстаткиТоваров.Остатки(

&КонецПериода,

Номенклатура В (

ВЫБРАТЬ

ПоступлениеТоваров.Номенклатура

ИЗ

Документ.ПоступлениеТоваров КАК ПоступлениеТоваров

ГДЕ

ПоступлениеТоваров.Дата <= &КонецПериода

)

) КАК ОстаткиТоваров

Эти примеры демонстрируют, как с помощью запросов можно решать типовые задачи: от простой выборки до сложных аналитических расчетов. Главное — понимать структуру данных и правильно формулировать условия.

FAQ: Ответы на частые вопросы о запросах в 1С

Можно ли в запросе использовать данные из внешних источников (например, Excel или JSON)?

Нет, запросы в работают только с данными, хранящимися в базе 1С:Предприятие. Для работы с внешними источниками нужно использовать другие механизмы: ЗагрузкаДанныхИзТабличногоДокумента, ЧтениеJSON или интеграцию через COM/HTTP-сервисы. Однако результаты внешней обработки можно передать в запрос через параметры или временные таблицы.

Как в запросе получить данные из подчиненного справочника (например, характеристики номенклатуры)?

Для этого используйте точку в пути к полю. Например, если у номенклатуры есть подчиненный справочник ХарактеристикиНоменклатуры, запрос будет выглядеть так:

ВЫБРАТЬ

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

Номенклатура.ХарактеристикиНоменклатуры.Наименование КАК Характеристика

ИЗ

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

Если связь не прямая, а через табличную часть, потребуется соединение таблиц.

Почему запрос с ЛЕВОЕ СОЕДИНЕНИЕ работает медленно?

Основные причины:

  1. Отсутствие фильтров по правой таблице (например, по дате или организации).
  2. Правая таблица содержит миллионы записей, и платформа вынужденно сканирует их все.
  3. Нет индексов по полям, используемым в условиях соединения.

Решения:

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

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

ВЫБРАТЬ

Документ.Ссылка,

Документ.Дата

ИЗ

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

ГДЕ

Документ.Дата >= НАЧАЛОМЕСЯЦА(&ТекущаяДата)

И Документ.Дата < НАЧАЛОМЕСЯЦА(&ТекущаяДата) + 32

Где &ТекущаяДата — параметр с текущей датой (можно передать ТекущаяДата из кода).

Можно ли в одном запросе обновить данные в базе?

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

  • ДокументОбъект.Записать — для документов;
  • СправочникОбъект.Записать — для справочников;
  • РегистрНакопленияОбъект.Записать — для регистров.

Для пакетного обновления можно использовать Объект.Выбрать в цикле или Запрос.ВыполнитьПакет (но это все равно не изменит данные напрямую).