Запросы в 1С:Предприятие — это мощный инструмент для извлечения, обработки и анализа данных из базы. Они позволяют получать информацию из справочников, документов, регистров и других объектов конфигурации без необходимости писать сложные циклы на встроенном языке. Понимание механизма работы запросов критично для разработчиков, администраторов и даже опытных пользователей, которые хотят автоматизировать отчеты или аналитику.
В отличие от традиционных SQL-запросов, синтаксис 1С-запросов имеет свои особенности: он адаптирован под специфику платформы, поддерживает работу с иерархическими данными и интегрирован с системой типов 1С. Однако многие принципы (например, соединения таблиц или агрегатные функции) остаются схожими. В этой статье мы разберем, как устроены запросы"под капотом", какие бывают виды конструкций, и как избежать типичных ошибок при их написании.
1. Архитектура запросов в 1С: как они выполняются
Когда вы пишете запрос в 1С, платформа преобразует его в набор операций над виртуальными таблицами — специальными представлениями данных, которые формируются на основе объектов конфигурации (справочников, документов, регистров и т.д.). Важно понимать, что запросы не работают напрямую с физической базой данных (будь то Microsoft SQL Server, PostgreSQL или файловая база). Вместо этого они оперируют абстракцией, которую предоставляет платформа.
Процесс выполнения запроса можно условно разделить на три этапа:
- 🔹 Парсинг и валидация — платформа проверяет синтаксис запроса, наличие используемых объектов в конфигурации и права доступа.
- 🔹 Оптимизация плана выполнения — система анализирует, как эффективнее получить данные (например, использовать индексы или кэш).
- 🔹 Исполнение и возвращение результата — формируется временная таблица с данными, которая передается в код на встроенном языке.
Один из ключевых моментов: 1С может кэшировать результаты запросов, если их структура и параметры не изменились. Это значительно ускоряет повторные обращения, но требует осторожности при работе с динамическими данными (например, в транзакциях).
2. Базовый синтаксис: структура запроса и ключевые конструкции
Минимальный запрос в 1С состоит из двух обязательных частей: указания источников данных (таблиц) и списка полей, которые нужно получить. Например:
ВЫБРАТЬ
Справочник.Номенклатура.Наименование КАК Наименование,
Справочник.Номенклатура.Артикул КАК Артикул
ИЗ
Справочник.Номенклатура КАК Справочник_Номенклатура
Основные конструкции, которые используются в запросах:
- 📌
ВЫБРАТЬ— указывает поля для выборки (аналогSELECTв SQL). - 📌
ИЗ— определяет источники данных (аналогFROM). - 📌
ГДЕ— фильтрация данных по условиям (аналогWHERE). - 📌
УПОРЯДОЧИТЬ ПО— сортировка результатов (аналогORDER BY). - 📌
ГРУППИРОВКА ПО— агрегация данных (аналогGROUP BY).
Особенность 1С — поддержка виртуальных таблиц, которые автоматически формируются для регистров накопления, бухгалтерии и других объектов. Например, таблица РегистрНакопления.ОстаткиТоваров.Остатки вернет актуальные остатки на указанную дату.
Используйте псевдонимы (алиасы) для таблиц и полей с ключевым словом КАК — это сделает запрос читабельнее и защитит от ошибок при изменении имен объектов в конфигурации.
3. Типы соединений таблиц и их влияние на производительность
В запросах 1С поддерживаются те же типы соединений, что и в SQL: внутренние (ВНУТРЕННЕЕ СОЕДИНЕНИЕ), левые (ЛЕВОЕ СОЕДИНЕНИЕ), правые и полные. Однако их реализация имеет нюансы из-за особенностей платформы.
Рассмотрим разницу на примере соединения справочника Номенклатура и документа ПоступлениеТоваров:
| Тип соединения | Синтаксис | Что возвращает | Когда использовать |
|---|---|---|---|
| Внутреннее | ВНУТРЕННЕЕ СОЕДИНЕНИЕ |
Только строки, где есть совпадения в обеих таблицах | Когда нужны только связанные данные |
| Левое | ЛЕВОЕ СОЕДИНЕНИЕ |
Все строки из левой таблицы + совпадения из правой (или NULL) |
Для отчетов, где важны все записи основной таблицы |
| Правое | ПРАВОЕ СОЕДИНЕНИЕ |
Все строки из правой таблицы + совпадения из левой | Редко используется в 1С, обычно заменяется левым с перестановкой таблиц |
Важный момент: левые соединения могут значительно замедлить запрос, если правая таблица содержит большое количество записей. Например, соединение документа РеализацияТоваров с регистром ОстаткиТоваров по полю Номенклатура без дополнительных фильтров приведет к полному сканированию регистра.
Всегда фильтруйте данные в соединениях по дате, организации или другим реквизитам, чтобы сократить объем обрабатываемых записей.
4. Агрегатные функции и группировка данных
Для анализа данных в запросах часто используются агрегатные функции: СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ и СРЕДНЕЕ. Они применяются в комбинации с конструкцией ГРУППИРОВКА ПО, которая определяет, по каким полям будут группироваться данные.
Пример запроса для расчета суммы продаж по номенклатуре:
ВЫБРАТЬ
Документ.РеализацияТоваров.Номенклатура КАК Номенклатура,
СУММА(Документ.РеализацияТоваров.Количество) КАК ОбщееКоличество,
СУММА(Документ.РеализацияТоваров.СуммаДокумента) КАК ОбщаяСумма
ИЗ
Документ.РеализацияТоваров КАК Документ_РеализацияТоваров
ГДЕ
Документ.РеализацияТоваров.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Документ.РеализацияТоваров.Номенклатура
Обратите внимание на параметры &НачалоПериода и &КонецПериода — это параметры запроса, которые можно передавать из кода на встроенном языке. Их использование делает запрос гибким и переиспользуемым.
Частые ошибки при группировке:
- ❌ Забывают добавить неагрегируемые поля в
ГРУППИРОВКА ПО(приводит к ошибке выполнения). - ❌ Используют
КОЛИЧЕСТВО(*)вместоКОЛИЧЕСТВО(Поле), что может давать неожиданные результаты при наличииNULL. - ❌ Не фильтруют данные перед группировкой, что приводит к избыточным вычислениям.
Что такое"перекрестное соединение" в 1С?
В 1С нет явного оператора CROSS JOIN, но его эффект можно получить, если указать несколько источников в секции ИЗ без условия соединения. Например:
ВЫБРАТЬ
Справочник.Номенклатура.Наименование КАК Номенклатура,
Справочник.Контрагенты.Наименование КАК Контрагент
ИЗ
Справочник.Номенклатура КАК Справочник_Номенклатура,
Справочник.Контрагенты КАК Справочник_Контрагенты
Такой запрос вернет декартово произведение двух справочников (все возможные комбинации строк), что крайне редко бывает полезно на практике и обычно является ошибкой.
5. Подзапросы и временные таблицы: когда и как использовать
Подзапросы в 1С позволяют встраивать один запрос внутрь другого, что полезно для сложной фильтрации или вычислений. Они могут использоваться в секциях ГДЕ, ВЫБРАТЬ или даже в ИЗ (как источник данных). Например:
ВЫБРАТЬ
Номенклатура.Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Артикул В (
ВЫБРАТЬ
ПоступлениеТоваров.Номенклатура.Артикул
ИЗ
Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
ГДЕ
ПоступлениеТоваров.Дата > &ДатаНачала
)
Временные таблицы — это механизм для хранения промежуточных результатов внутри одного запроса. Они создаются с помощью конструкции ПОМЕСТИТЬ... ВО ВРЕМЕННУЮ ТАБЛИЦУ и могут использоваться для:
- 🔄 Упрощения сложных запросов (разбиение на логические блоки).
- 🔄 Повторного использования одних и тех же данных без дублирования кода.
- 🔄 Оптимизации производительности (платформа может кэшировать временные таблицы).
Пример с временной таблицей:
ВЫБРАТЬ
Поступление.Номенклатура КАК Номенклатура,
СУММА(Поступление.Количество) КАК Поступило
ПОМЕСТИТЬ ПоступленияЗаПериод
ИЗ
Документ.ПоступлениеТоваров КАК Поступление
ГДЕ
Поступление.Дата МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
Поступление.Номенклатура
//////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПоступленияЗаПериод.Номенклатура КАК Номенклатура,
ПоступленияЗаПериод.Поступило,
ПродажиЗаПериод.Продано
ИЗ
ПоступленияЗаПериод КАК ПоступленияЗаПериод
ЛЕВОЕ СОЕДИНЕНИЕ ВРЕМЕННАЯ ТАБЛИЦА ПродажиЗаПериод КАК ПродажиЗаПериод
ПО ПоступленияЗаПериод.Номенклатура = ПродажиЗаПериод.Номенклатура
🔲 Убедитесь, что временная таблица действительно нужна (нельзя ли обойтись подзапросом?)
🔲 Проверьте, что имена временных таблиц уникальны в пределах запроса
🔲 Не создавайте временные таблицы с большим объемом данных без необходимости
🔲 Используйте индексируемые поля для соединений с временными таблицами
-->
6. Оптимизация запросов: как ускорить выполнение
Медленные запросы — одна из самых распространенных проблем в 1С, особенно в крупных базах с миллионами записей. Основные причины тормозов:
- 🐢 Отсутствие фильтров по датам или другим индексируемым полям.
- 🐢 Чрезмерное использование
ЛЕВОЕ СОЕДИНЕНИЕбез ограничений. - 🐢 Выборка ненужных полей (например,
ВЫБРАТЬ *). - 🐢 Сложные вычисления в секции
ВЫБРАТЬ(лучше перенести их в код на встроенном языке).
Практические советы по оптимизации:
- Всегда фильтруйте данные по датам, организациям или другим реквизитам, которые имеют индексы.
- Используйте
РАЗЛИЧНЫЕдля исключения дублей, если они не нужны. - Избегайте функций над полями в условиях (например,
ГДЕ ЛЕВ(Наименование, 3) ="АБВ"— это блокирует использование индексов). - Для больших выборок используйте
ПАКЕТНЫЙ РЕЖИМилиПОМЕСТИТЬ В МАССИВ.
Пример оптимизированного запроса для выборки документов:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Документ.Ссылка КАК Ссылка,
Документ.Дата КАК Дата,
Документ.СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваров КАК Документ
ГДЕ
Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Документ.Организация = &ТекущаяОрганизация
УПОРЯДОЧИТЬ ПО
Документ.Дата
Используйте инструмент"План запроса" в конфигураторе (меню Администрирование → Тестирование и исправление → План запроса), чтобы анализировать, как платформа выполняет ваш запрос и где возникают"узкие места".
7. Типичные ошибки и как их избегать
Даже опытные разработчики иногда допускают ошибки при написании запросов. Вот наиболее распространенные из них:
⚠️ Внимание: Если в запросе используется виртуальная таблица регистра срезом последних, убедитесь, что дата в параметре НаДату не превышает текущую дату базы. Иначе запрос вернет пустой результат, так как данные еще не сформированы.
Ошибки и способы их исправления:
| Ошибка | Причина | Как исправить |
|---|---|---|
| "Поле не найдено" | Опечатка в имени поля или объекта | Проверьте регистр и синтаксис (например, Номенклатура.Наименование, а не Наименование) |
| "Недопустимое использование агрегатной функции" | Агрегатная функция (например, СУММА) используется без ГРУППИРОВКА ПО |
Добавьте группировку или уберите агрегатную функцию |
| Запрос выполняется слишком долго | Отсутствуют фильтры по индексируемым полям | Добавьте условия по дате, организации или другим реквизитам с индексами |
| "Типы не совпадают" | Попытка сравнить поля разных типов (например, строку и число) | Используйте явное приведение типов (например, ЧИСЛО(Поле)) |
Еще одна распространенная проблема — некорректная работа с параметрами. Например, если параметр не инициализирован или имеет неверный тип, запрос может вернуть неожиданные результаты. Всегда проверяйте значения параметров перед выполнением запроса:
Если НЕ ЗначениеЗаполнено(НачалоПериода) Тогда
НачалоПериода = НачалоДня(ТекущаяДата);
КонецЕсли;
8. Практическое применение: примеры запросов для задач
Рассмотрим несколько реальных примеров запросов, которые часто требуются в работе:
1. Выборка документов с детализацией по строкам табличной части:
ВЫБРАТЬ
Документ.Ссылка КАК Документ,
Документ.Дата КАК Дата,
Документ.Товары.Номенклатура КАК Номенклатура,
Документ.Товары.Количество КАК Количество,
Документ.Товары.Цена КАК Цена,
Документ.Товары.Сумма КАК СуммаСтроки
ИЗ
Документ.РеализацияТоваров КАК Документ
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваров.Товары КАК Документ_Товары
ПО Документ.Ссылка = Документ_Товары.Ссылка
ГДЕ
Документ.Дата МЕЖДУ &Начало И &Конец
2. Поиск дублей в справочнике по нескольким полям:
ВЫБРАТЬ
Наименование,
Артикул,
КОЛИЧЕСТВО(*) КАК Количество
ИЗ
Справочник.Номенклатура КАК Номенклатура
СГРУППИРОВАТЬ ПО
Наименование,
Артикул
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) > 1
3. Расчет остатков товара на дату с учетом движений:
ВЫБРАТЬ
ОстаткиТоваров.Номенклатура КАК Номенклатура,
ОстаткиТоваров.КоличествоОстаток КАК Остаток
ИЗ
РегистрНакопления.ОстаткиТоваров.Остатки(
&КонецПериода,
Номенклатура В (
ВЫБРАТЬ
ПоступлениеТоваров.Номенклатура
ИЗ
Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
ГДЕ
ПоступлениеТоваров.Дата <= &КонецПериода
)
) КАК ОстаткиТоваров
Эти примеры демонстрируют, как с помощью запросов можно решать типовые задачи: от простой выборки до сложных аналитических расчетов. Главное — понимать структуру данных и правильно формулировать условия.
FAQ: Ответы на частые вопросы о запросах в 1С
Можно ли в запросе использовать данные из внешних источников (например, Excel или JSON)?
Нет, запросы в 1С работают только с данными, хранящимися в базе 1С:Предприятие. Для работы с внешними источниками нужно использовать другие механизмы: ЗагрузкаДанныхИзТабличногоДокумента, ЧтениеJSON или интеграцию через COM/HTTP-сервисы. Однако результаты внешней обработки можно передать в запрос через параметры или временные таблицы.
Как в запросе получить данные из подчиненного справочника (например, характеристики номенклатуры)?
Для этого используйте точку в пути к полю. Например, если у номенклатуры есть подчиненный справочник ХарактеристикиНоменклатуры, запрос будет выглядеть так:
ВЫБРАТЬ
Номенклатура.Наименование КАК Номенклатура,
Номенклатура.ХарактеристикиНоменклатуры.Наименование КАК Характеристика
ИЗ
Справочник.Номенклатура КАК Номенклатура
Если связь не прямая, а через табличную часть, потребуется соединение таблиц.
Почему запрос с ЛЕВОЕ СОЕДИНЕНИЕ работает медленно?
Основные причины:
- Отсутствие фильтров по правой таблице (например, по дате или организации).
- Правая таблица содержит миллионы записей, и платформа вынужденно сканирует их все.
- Нет индексов по полям, используемым в условиях соединения.
Решения:
- Добавьте фильтры в секцию
ГДЕдля правой таблицы. - Используйте
ВНУТРЕННЕЕ СОЕДИНЕНИЕ, если не нужны строки без совпадений. - Проверьте наличие индексов в конфигураторе (меню
Администрирование → Индексы базы данных).
Как в запросе получить данные за текущий месяц без жесткого указания дат?
Используйте функции работы с датами прямо в запросе:
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата
ИЗ
Документ.РеализацияТоваров КАК Документ
ГДЕ
Документ.Дата >= НАЧАЛОМЕСЯЦА(&ТекущаяДата)
И Документ.Дата < НАЧАЛОМЕСЯЦА(&ТекущаяДата) + 32
Где &ТекущаяДата — параметр с текущей датой (можно передать ТекущаяДата из кода).
Можно ли в одном запросе обновить данные в базе?
Нет, запросы в 1С предназначены только для чтения данных. Для изменения информации используйте объекты встроенного языка:
ДокументОбъект.Записать— для документов;СправочникОбъект.Записать— для справочников;РегистрНакопленияОбъект.Записать— для регистров.
Для пакетного обновления можно использовать Объект.Выбрать в цикле или Запрос.ВыполнитьПакет (но это все равно не изменит данные напрямую).