Работа с базами данных в 1С:Предприятие невозможна без умения составлять запросы. Этот инструмент позволяет извлекать, фильтровать и анализировать данные с минимальными затратами времени. Однако для новичков синтаксис запросов часто становится настоящей головной болью: непонятные конструкции, ошибки выполнения и неожиданные результаты отбивают желание разбираться в этой теме.
На практике 80% задач в 1С решаются с помощью всего 20% возможностей языка запросов. В этой статье мы разберём базовые принципы, покажем работающие примеры и раскроем секреты, которые экономят часы работы. Вы научитесь не только копировать готовые запросы, но и адаптировать их под свои нужды — от простого выборки справочников до сложных многотабличных соединений.
Особое внимание уделим конструктору запросов — инструменту, который упрощает жизнь начинающим разработчикам, но часто игнорируется опытными программистами. А ещё вы узнаете, как избежать типичных ошибок, из-за которых запросы работают медленно или возвращают неверные данные.
Что такое запрос в 1С и зачем он нужен
Запрос в 1С:Предприятие 8 — это специализированный язык для работы с данными, напоминающий SQL, но адаптированный под особенности платформы. С его помощью можно:
- 📊 Выгружать данные из справочников, документов и регистров
- 🔍 Фильтровать записи по сложным условиям
- 🔄 Группировать и агрегировать информацию (суммы, средние значения)
- 🔗 Соединять несколько таблиц в одном результате
Главное отличие от прямого обращения к объектам 1С (например, через Выбрать) — это возможность работать с виртуальными таблицами регистров, которые содержат исторические данные и остатки. Например, запрос может вернуть остатки товаров на любую дату, в то время как прямой обход документов потребует сложной логики.
Без запросов невозможно:
- 📈 Строить аналитические отчёты с произвольными разрезами
- 🤖 Автоматизировать рутинные операции (например, массовое изменение цен)
- 🔧 Интегрировать 1С с внешними системами через обмен данными
Способы создания запросов: конструктор vs ручной ввод
В 1С есть два основных способа формирования запросов: через конструктор и в ручном режиме. У каждого подхода свои плюсы и минусы.
| Критерии | Конструктор запросов | Ручной ввод |
|---|---|---|
| Скорость разработки | ⚡ Быстро для простых запросов | 🐢 Медленнее, но гибче |
| Сложность запроса | 🟡 Ограничен функционалом интерфейса | 🟢 Поддерживает все возможности языка |
| Ошибки синтаксиса | 🛡️ Минимизированы | ⚠️ Требует внимательности |
| Использование в коде | 🔄 Нужно копировать результат | 📝 Пишется непосредственно в модуле |
Конструктор удобен для:
- 🔍 Быстрого прототипирования (например, чтобы понять структуру данных)
- 📋 Формирования отчётов с визуальной настройкой полей
- 🤝 Обучения новичков (наглядно показывает связи между таблицами)
Ручной ввод незаменим, когда нужно:
- 🔧 Использовать сложные выражения (например,
ВЫБОР КОГДА...) - ⚡ Оптимизировать производительность (конструктор иногда генерирует избыточный код)
- 🔄 Динамически формировать текст запроса в зависимости от условий
Если вы только начинаете осваивать запросы, попробуйте такой приём: сначала составьте запрос в конструкторе, затем переключитесь в режим текста (Текст) и изучите сгенерированный код. Это поможет понять синтаксис на живых примерах.
Базовый синтаксис: структура запроса
Любой запрос в 1С состоит из обязательных и необязательных секций. Минимальная рабочая конструкция выглядит так:
ВЫБРАТЬ
[СписокПолей]
ИЗ
[ИсточникДанных]
[ГДЕ
[УсловияОтбора]]
Разберём на примере выборки всех контрагентов:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
Контрагенты.Наименование КАК Название
ИЗ
Справочник.Контрагенты КАК Контрагенты
Ключевые элементы:
ВЫБРАТЬ— указывает, какие поля нужно вернутьИЗ— определяет источник данных (справочник, документ, регистр)КАК— присваивает псевдоним полю или таблице (обязательно для сложных запросов)
Для фильтрации добавляется секция ГДЕ:
ВЫБРАТЬ
Номенклатура.Наименование,
Номенклатура.Артикул
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ПометкаУдаления
Что будет если не указать псевдонимы (КАК)?
Если не использовать псевдонимы для полей с одинаковыми именами из разных таблиц, 1С выдаст ошибку"Неоднозначное имя поля". Например, если в запросе участвуют таблицы Документ.ПоступлениеТоваров и Документ.РеализацияТоваров, обе из которых содержат поле Дата, без псевдонимов платформа не поймёт, какое именно поле вы имеете в виду.
Практические примеры запросов
Теория становится понятнее на живых примерах. Рассмотримные задачи, с которыми сталкиваются пользователи 1С.
1. Простая выборка из справочника
Задача: получить список всех активных номенклатурных позиций с ценами.
ВЫБРАТЬ
Номенклатура.Наименование КАК Товар,
Номенклатура.Артикул,
Цены.Цена КАК ТекущаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЦеныНоменклатуры КАК Цены
ПО Номенклатура.Ссылка = Цены.Номенклатура
ГДЕ
НЕ Номенклатура.ПометкаУдаления
И Цены.ТипЦен = &ТипЦены
Обратите внимание на:
- 🔗
ЛЕВОЕ СОЕДИНЕНИЕ— включает все товары, даже если у них нет цены - 🔍 Параметр
&ТипЦены— позволяет передавать значение извне
2. Агрегация данных (суммы, количество)
Задача: посчитать общую сумму продаж по каждому контрагенту за месяц.
ВЫБРАТЬ
Реализация.Контрагент КАК Покупатель,
СУММА(Реализация.СуммаДокумента) КАК ОбщаяСумма,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Реализация.Ссылка) КАК КоличествоДокументов
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца
СГРУППИРОВАТЬ ПО
Реализация.Контрагент
Здесь используются:
- 📊 Агрегатные функции:
СУММА,КОЛИЧЕСТВО - 📅 Фильтрация по дате с параметрами
&НачалоМесяцаи&КонецМесяца - 🔗 Группировка по полю
Контрагент
Указаны все необходимые поля в секции ВЫБРАТЬ|
Правильно расставлены псевдонимы (КАК) для полей|
Все параметры (&Имя) имеют значения по умолчанию|
Секция ГДЕ содержит корректные условия отбора|
Для соединений таблиц использованы правильные типы (ВНУТРЕННЕЕ, ЛЕВОЕ и т.д.)-->
Работа с параметрами и динамические запросы
Статичные запросы удобны для разовых задач, но в реальной разработке часто требуется динамически формировать текст запроса в зависимости от условий. Для этого используются параметры и программное конструирование строки запроса.
Параметры позволяют передавать значения в запрос извне. Они обозначаются символом & и должны быть объявлены в начале:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Клиенты.Наименование КАК Клиент,
| Клиенты.ИНН
|ИЗ
| Справочник.Контрагенты КАК Клиенты
|ГДЕ
| Клиенты.ВидКонтрагента = &ВидКонтрагента
| И НЕ Клиенты.ПометкаУдаления";
Запрос.УстановитьПараметр("ВидКонтрагента", ВидыКонтрагентов.Покупатель);
Результат = Запрос.Выполнить;
Для динамического формирования текста запроса используйте СтрокаЗапроса:
ТекстЗапроса ="ВЫБРАТЬ |";
Если НужныЦены Тогда
ТекстЗапроса = ТекстЗапроса +"Цены.Цена КАК ТекущаяЦена, |";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса +
"Номенклатура.Наименование КАК Товар |
ИЗ Справочник.Номенклатура КАК Номенклатура |";
Если НужныЦены Тогда
ТекстЗапроса = ТекстЗапроса +
"ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЦеныНоменклатуры КАК Цены |
ПО Номенклатура.Ссылка = Цены.Номенклатура |";
КонецЕсли;
Всегда проверяйте динамически сформированные запросы на наличие SQL-инъекций. Никогда не подставляйте в текст запроса значения, полученные от пользователя, без предварительной обработки. Используйте параметры (&Имя) вместо конкатенации строк.
Типичные ошибки при работе с параметрами:
- ❌ Забывают установить значение параметра (
УстановитьПараметр) - ❌ Используют одинаковые имена для параметров и полей
- ❌ Передают несовместимые типы данных (например, строку вместо даты)
Оптимизация запросов: как ускорить выполнение
Медленные запросы — одна из главных причин тормозов в 1С. Оптимизация требует понимания того, как платформа выполняет запросы и какие операции наиболее затратны.
Основные правила оптимизации:
- 🎯 Избегайте выборки всех полей (
ВЫБРАТЬ *) — указывайте только необходимые - 🔍 Используйте индексированные поля в условиях отбора (например,
Ссылка,Дата) - 📊 Сокращайте объём данных на ранних этапах (фильтруйте в секции
ГДЕ, а не после получения результата) - 🔗 Ограничивайте соединения таблиц — каждое дополнительное соединение увеличивает время выполнения
Пример неоптимального и оптимизированного запроса:
| Плохой вариант | Хороший вариант | Причина улучшения |
|---|---|---|
|
|
Выборка только нужных полей |
|
|
Исключение дубликатов с помощью РАЗЛИЧНЫЕ |
Для анализа производительности используйте:
- 🔍 План выполнения запроса (включается через
Запрос.АнализироватьТекст) - ⏱️ Замер времени выполнения с помощью
ПолучитьФорматированнуюСтроку(ТекущаяДата,"ДФ=dd.MM.yyyy HH:mm:ss.fff") - 📊 Тестирование на больших объёмах данных (иногда запрос работает быстро на 100 записях, но"падает" на 100 000)
Если запрос выполняется больше 5 секунд, скорее всего, он требует оптимизации. Для сложных отчётов рассмотрите возможность предварительного расчёта данных и сохранения их в регистрах сведений.
Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданными ошибками при работе с запросами. Разберём самые распространённые случаи.
⚠️ Внимание: Если в запросе используются виртуальные таблицы регистров (например, РегистрНакопления.ОстаткиТоваров.Остатки), обязательно проверяйте корректность передачи параметров отбора. Неправильная дата или пустое значение может привести к выборке всех записей за всю историю, что загрузит сервер.
Ошибка 1:"Поле не найдено"
Причина: опечатка в имени поля или таблицы, либо поле действительно отсутствует в источнике данных.
Решение:
- Проверьте точное имя поля через
Метаданныеили конструктор запросов - Убедитесь, что используете правильный псевдоним таблицы
- Для виртуальных таблиц проверьте синтаксис (например,
ОстаткивместоОстатки)
Ошибка 2:"Недопустимое использование агрегатной функции"
Причина: в запросе с СГРУППИРОВАТЬ ПО пытаетесь вывести поле, не указанное в группировке.
Решение: либо добавьте поле в СГРУППИРОВАТЬ ПО, либо примените к нему агрегатную функцию (например, МАКСИМУМ).
Ошибка 3: Запрос выполняется слишком долго или"подвисает"
Причины и решения:
- 🔄 Циклические связи — проверьте, не соединяете ли вы таблицы по полям, которые ссылаются друг на друга
- 🗃️ Отсутствие индексов — добавьте индексированные поля в условия отбора
- 📊 Слишком широкий диапазон дат — ограничьте период выборки
Ошибка 4: Неверные результаты (дубли, пропущенные записи)
Частые причины:
- 🔗 Неправильный тип соединения (
ВНУТРЕННЕЕвместоЛЕВОЕ) - 📅 Ошибки в условиях по датам (например, использование
=вместоМЕЖДУ) - 🔍 Неучтённые пометки удаления (забыли добавить
И НЕ ПометкаУдаления)
Как найти проблемное место в медленном запросе?
1. Разбейте сложный запрос на несколько простых и проверьте время выполнения каждого.
2. Используйте ОБЪЕДИНИТЬ ВСЕ вместо подзапросов — иногда это ускоряет выполнение.
3. Проверьте, не тянутся ли лишние данные через соединения таблиц. Например, если вам нужны только справочники, не присоединяйте документы без необходимости.
Продвинутые техники: подзапросы, временные таблицы, пакетные запросы
Когда стандартных возможностей запросов недостаточно, на помощь приходят продвинутые техники. Они требуют больше опыта, но позволяют решать задачи, которые иначе пришлось бы реализовывать на встроенном языке.
1. Подзапросы
Позволяют использовать результат одного запроса внутри другого. Пример: выборка товаров, которые продавались в текущем месяце:
ВЫБРАТЬ
Номенклатура.Наименование КАК Товар
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В (
ВЫБРАТЬ РАЗЛИЧНЫЕ
Товары.Номенклатура
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Ссылка.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца
)
2. Временные таблицы
Полезны для хранения промежуточных результатов. Создаются с помощью #Имя:
ВЫБРАТЬ
Товары.Номенклатура КАК Номенклатура,
СУММА(Товары.Количество) КАК Количество
ИЗ
Документ.ПоступлениеТоваров.Товары КАК Товары
ГДЕ
Товары.Ссылка.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
ПОМЕСТИТЬ ВТПоступления
// Далее используем временную таблицу
ВЫБРАТЬ
Поступления.Номенклатура.Наименование КАК Товар,
Поступления.Количество
ИЗ
ВТПоступления КАК Поступления
3. Пакетные запросы
Позволяют выполнить несколько запросов за один вызов сервера:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ СУММА(Сумма) КАК ИтогоПродажи ИЗ Документ.РеализацияТоваровУслуг;
////////////////////////////////////////////////
ВЫБРАТЬ СУММА(Сумма) КАК ИтогоПоступления ИЗ Документ.ПоступлениеТоваровУслуг";
Результат = Запрос.ВыполнитьПакет;
ТаблицаПродаж = Результат[0].Выгрузить;
ТаблицаПоступлений = Результат[1].Выгрузить;
Пакетные запросы удобны когда:
- 📊 Нужно получить несколько независимых наборов данных
- ⚡ Хочется сократить количество обращений к серверу
- 🔄 Данные из одного запроса не зависят от результатов другого
FAQ: Ответы на частые вопросы
Как узнать структуру таблицы для запроса?
Есть несколько способов:
- Используйте конструктор запросов — он показывает все доступные поля.
- Посмотрите в
Метаданные(правый клик на объекте →"Перейти к метаданным"). - Для виртуальных таблиц регистров смотрите описание в синтакс-помощнике (
F1по ключевому слову, например,РегистрНакопления).
Для документов полезно знать, что табличные части доступны через точку: Документ.РеализацияТоваровУслуг.Товары.
Можно ли в запросе использовать данные из другой базы?
Прямо в языке запросов 1С — нет. Но есть обходные пути:
- 🔗 Распределённые информационные базы (если базы связаны)
- 📥 Обмен данными через XML, JSON или универсальные форматы
- 🖥️ Внешние источники данных (начиная с версии 8.3.14)
Для простых случаев можно загрузить данные из внешней базы в временную таблицу, а затем использовать её в запросе.
Почему запрос возвращает пустую таблицу, хотя данные есть?
Частые причины:
- ❌ Ошибка в условиях отбора (например, неверный диапазон дат)
- ❌ Пометки удаления — забыли добавить
И НЕ ПометкаУдаления - ❌ Неправильные соединения таблиц (например,
ВНУТРЕННЕЕвместоЛЕВОЕ) - ❌ Ошибки в параметрах — не установлено значение или неверный тип
Для диагностики:
- Упростите запрос до минимального рабочего варианта.
- Проверьте каждый параметр с помощью
Сообщить. - Используйте конструктор запросов для визуальной проверки.
Как экспортировать результат запроса в Excel?
Самый простой способ:
Результат = Запрос.Выполнить;
Таблица = Результат.Выгрузить;
Таблица.Записать("C:\Temp\Отчет.xlsx", ТипФайлаExcel.Xlsx);
Для более гибкого экспорта:
- Используйте
ЗначениеВСтрокуВнутрдля форматирования данных. - Настройте стили ячеек через
ОбъектExcel = Новый COMОбъект("Excel.Application"). - Для больших таблиц разбейте экспорт на части, чтобы избежать зависаний.
⚠️ Внимание: При работе с COM-объектами Excel убедитесь, что на компьютере пользователя установлен Microsoft Excel соответствующей версии. В противном случае код вызовет ошибку.
Можно ли в запросе использовать свои функции?
Нет, в языке запросов 1С нельзя определять пользовательские функции. Однако есть альтернативы:
- 🔧 Встроенные функции:
НАЧСТРОКИ,ДЛСТР,ВЫБОР КОГДА...и другие. - 📝 Вычисления после выполнения запроса — обработайте результат в коде на встроенном языке.
- 🗃️ Временные таблицы — можно предварительно рассчитать значения и присоединить их к основному запросу.
Пример использования встроенных функций:
ВЫБРАТЬ
Клиенты.Наименование КАК Клиент,
ВЫБОР
КОГДА Клиенты.ИНН =""
ТОГДА"Без ИНН"
ИНАЧЕ Клиенты.ИНН
КОНЕЦ КАК ИНН