Если вы только начинаете осваивать 1С:Предприятие, термин «запрос» может показаться абстрактным. На самом деле это один из ключевых инструментов работы с данными — без него невозможно построить отчёты, реализовать сложную логику или оптимизировать производительность системы. В этой статье мы разберём, что такое запрос в 1С, зачем он нужен, какие бывают виды запросов и как их правильно составлять.

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

Что такое запрос в 1С простыми словами

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

  • 📊 Отбирать нужные записи (например, все документы за последний месяц).
  • 🔄 Сортировать и группировать данные (скажем, по контрагентам или датам).
  • 🧩 Объединять информацию из разных таблиц (например, данные о товарах и их остатках).
  • Вычислять агрегированные значения (суммы, средние, количества).

Главное отличие от «ручного» перебора данных в коде — запросы выполняются на стороне сервера базы данных, что значительно ускоряет работу с большими объёмами информации. Например, если вам нужно найти все неоплаченные счета клиента, запрос сделает это за доли секунды, тогда как цикл на встроенном языке мог бы занять минуты.

Язык запросов поддерживает:

  • 🔹 ВЫБРАТЬ (аналог SELECT в SQL) — выборка полей.
  • 🔹 ГДЕ (WHERE) — условия отбора.
  • 🔹 СГРУППИРОВАТЬ ПО (GROUP BY) — группировка.
  • 🔹 УПОРЯДОЧИТЬ ПО (ORDER BY) — сортировка.
  • 🔹 ОБЪЕДИНИТЬ (UNION) — объединение результатов.
📊 Как часто вы используете запросы в 1С?
Постоянно, это моя основная работа
Иногда, для отчётов или доработок
Рядом не стоял, только слышал
Не знаю, что это такое

Виды запросов в 1С: от простых к сложным

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

Тип запроса Пример использования Особенности
Простой запрос Выборка всех документов «Заказ клиента» за текущий день Один источник данных, минимальные условия отбора
Запрос с объединением Связь таблиц «Товары» и «Остатки» для анализа доступности Использует СОЕДИНИТЬ или ЛЕВОЕ СОЕДИНЕНИЕ
Иерархический запрос Вывод справочника «Номенклатура» с учётом групп и подгрупп Работает с параметром ИЕРАРХИЯ
Запрос с временными таблицами Промежуточные расчёты для сложных отчётов Использует ПОМЕСТИТЬ для хранения временных данных
Пакетный запрос Выполнение нескольких запросов в одной транзакции Оптимизирует производительность при массовых операциях

Например, иерархический запрос незаменим, когда нужно вывести дерево справочника (например, «Номенклатура» с группами «Одежда → Куртки → Зимние»). А запросы с временными таблицами позволяют разбивать сложные расчёты на этапы, что упрощает отладку и повышает скорость выполнения.

💡

Если запрос выполняется слишком долго, проверьте наличие индексов на полях, используемых в условиях ГДЕ. Например, для поля «Дата» в документах индекс создаётся автоматически, а для пользовательских реквизитов может потребоваться ручная настройка.

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

Базовая структура запроса в выглядит так:

ВЫБРАТЬ

[ПоляДляВыбора]

ИЗ

[ИсточникДанных] КАК [Псевдоним]

ГДЕ

[УсловияОтбора]

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

[ПоляГруппировки]

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

[ПоляСортировки]

Разберём ключевые элементы:

  • 📌 ВЫБРАТЬ — перечисляет поля, которые нужно получить. Можно использовать * для выборки всех полей, но это не рекомендуется из-за снижения производительности.
  • 📌 ИЗ — указывает источник данных (таблицу документа, справочника или виртуальную таблицу).
  • 📌 ГДЕ — задаёт условия фильтрации (например, Дата >= &НачалоПериода).
  • 📌 СГРУППИРОВАТЬ ПО — используется для агрегатных функций (СУММА, КОЛИЧЕСТВО).

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

ВЫБРАТЬ

СчетНаОплату.Номер КАК НомерСчета,

СчетНаОплату.Дата КАК ДатаСчета,

СчетНаОплату.Сумма КАК Сумма

ИЗ

Документ.СчетНаОплату КАК СчетНаОплату

ГДЕ

СчетНаОплату.СтатусОплаты = ЗНАЧЕНИЕ(Перечисление.СтатусыОплаты.НеОплачен)

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

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

ДатаСчета

Что такое виртуальные таблицы в 1С?

Виртуальные таблицы — это специальные представления данных, которые платформа создаёт «на лету» для удобства работы. Например, таблица Документ.ЗаказКлиента.Остатки автоматически рассчитывает остатки товаров по заказам, хотя физически таких данных в базе может не существовать. Их не нужно обновлять вручную — они всегда актуальны.

Где и как выполняются запросы в 1С

Запросы можно выполнять в нескольких местах:

  1. В конфигураторе — для отладки и тестирования (меню Сервис → Запрос (Ctrl+Alt+Q)). Здесь удобно проверять синтаксис и просматривать результаты.
  2. В модулях — в обработках, отчётах или документах. Например, в обработке проведения документа можно добавить запрос для проверки остатков.
  3. В внешних отчётах/обработках — для расширенного анализа данных.
  4. В языке 1С — с помощью объекта Запрос и методов Выполнить(), Выгрузить().

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

| СУММА(Документ.РеализацияТоваровУслуг.Количество) КАК Продажи

|ИЗ

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

| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

| ПО Реализация.Номенклатура = Номенклатура.Ссылка

|ГДЕ

| Реализация.Дата МЕЖДУ &Начало И &Конец

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

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

Запрос.УстановитьПараметр("Начало", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("Конец", КонецМесяца(ТекущаяДата()));

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

💡

Всегда используйте параметры (УстановитьПараметр) вместо прямой подстановки значений в текст запроса. Это защищает от SQL-инъекций и упрощает поддержку кода.

Это гарантирует целостность данных, но требует внимательного отношения к сложным операциям.

Типичные ошибки при работе с запросами и как их избежать

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

⚠️ Внимание: Если в запросе используется поле с типом ХранилищеЗначения (например, для хранения двоичных данных), его нельзя напрямую сравнивать с другими полями. Сначала нужно извлечь значение с помощью функции ЗНАЧЕНИЕ().
  • Отсутствие индексов на полях, используемых в ГДЕ или СГРУППИРОВАТЬ ПО. Это приводит к полному сканированию таблиц и замедлению работы.
  • Избыточная выборка (например, ВЫБРАТЬ *). Всегда указывайте только необходимые поля.
  • Неправильные соединения таблиц. ЛЕВОЕ СОЕДИНЕНИЕ и ВНУТРЕННЕЕ СОЕДИНЕНИЕ дают разные результаты — первое возвращает все записи из левой таблицы, даже если нет совпадений.
  • Игнорирование временных зон. При работе с датами учитывайте настройки временной зоны в базе.

Пример ошибки с соединением:

// Некорректно: внутреннее соединение отсечёт документы без указанного контрагента

ВЫБРАТЬ

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

ИЗ

Документ.ЗаказКлиента КАК Документы

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты

ПО Документы.Контрагент = Контрагенты.Ссылка

// Правильно: левое соединение сохранит все заказы

ВЫБРАТЬ

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

ИЗ

Документ.ЗаказКлиента КАК Документы

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты

ПО Документы.Контрагент = Контрагенты.Ссылка

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

Оптимизация запросов: как ускорить работу

Медленные запросы — одна из главных причин тормозов в . Вот несколько способов их оптимизировать:

Использовать индексированные поля в условиях ГДЕ

Избегать ВЫБРАТЬ * — указывать только нужные поля

Заменять подзапросы соединениями (СОЕДИНИТЬ)

Использовать временные таблицы для сложных расчётов

Ограничивать объём данных параметрами дат или статусов-->

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

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

ВЫБРАТЬ

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

(ВЫБРАТЬ СУММА(Сумма)

ИЗ Документ.Оплата КАК Оплата

ГДЕ Оплата.Заказ = Документы.Ссылка) КАК Оплачено

ИЗ

Документ.ЗаказКлиента КАК Документы

// Быстрый вариант: соединение таблиц

ВЫБРАТЬ

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

СУММА(Оплаты.Сумма) КАК Оплачено

ИЗ

Документ.ЗаказКлиента КАК Документы

ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплаты

ПО Оплаты.Заказ = Документы.Ссылка

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

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

Ещё один эффективный приём — использование виртуальных таблиц. Например, вместо ручного расчёта остатков по регистру можно обратиться к виртуальной таблице РегистрНакопления.ОстаткиТоваров.Остатки(), которая уже оптимизирована платформой.

⚠️ Внимание: При работе с большими базами (более 100 ГБ) избегайте операций, требующих полного сканирования таблиц, таких как ПОДОБНО (LIKE) с символом % в начале строки. Это может заблокировать базу на долгое время.

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

Рассмотрим несколько реальных сценариев, где запросы незаменимы:

1. Отчёт по продажам с группировкой по менеджерам

ВЫБРАТЬ

Менеджер.Наименование КАК Менеджер,

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

КОЛИЧЕСТВО(Продажи.Ссылка) КАК КоличествоСделок

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК Менеджер

ПО Продажи.Ответственный = Менеджер.Ссылка

ГДЕ

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

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

Менеджер.Наименование

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

ОбщаяСумма УБЫВ

2. Поиск дублей в справочнике контрагентов

ВЫБРАТЬ

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

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

ИЗ

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

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

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

ИМЕЮЩИЕ

КОЛИЧЕСТВО(Контрагенты.Ссылка) > 1

3. Анализ движения товаров по складам

ВЫБРАТЬ

Товары.Наименование КАК Товар,

Склады.Наименование КАК Склад,

СУММА(Движения.КоличествоПриход) КАК Приход,

СУММА(Движения.КоличествоРасход) КАК Расход

ИЗ

РегистрНакопления.ТоварыНаСкладах.Обороты(&Начало, &Конец,) КАК Движения

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Товары

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Склады КАК Склады

ПО Движения.Склад = Склады.Ссылка

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

Товары.Наименование,

Склады.Наименование

Эти примеры показывают, как с помощью запросов можно решать типовые бизнес-задачи без написания сложного кода на встроенном языке.

FAQ: Частые вопросы о запросах в 1С

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

Нет, язык запросов работает только с данными внутри базы. Для интеграции с внешними источниками нужно сначала загрузить данные в (например, через ЗагрузкаДанных или HTTPСервис), а затем использовать их в запросах.

Как отладить запрос, если он возвращает неверные данные?

Используйте пошаговую отладку в конфигураторе:

  1. Откройте запрос в конструкторе (Ctrl+Alt+Q).
  2. Нажмите Выполнить и проверьте результат.
  3. Если ошибка в условиях, разбейте запрос на части (например, сначала проверьте только ГДЕ, затем добавьте СГРУППИРОВАТЬ ПО).
  4. Для сложных запросов используйте ОбъяснитьЗапрос(), чтобы увидеть план выполнения.

Чем запрос отличается от объекта «ДанныеФормы»?

Запрос работает напрямую с базой данных и оптимизирован для выборки больших объёмов информации. ДанныеФормы — это коллекция объектов в памяти, которая подходит для небольших наборов данных (например, для отображения в таблице формы). Запросы обычно используют для первичной выборки, а ДанныеФормы — для взаимодействия с пользователем.

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

Да, но с осторожностью! Для этого используются конструкции:

  • ОБНОВИТЬ [Таблица] УСТАНОВИТЬ [Поле1] = [Значение1] — изменяет существующие записи.
  • УДАЛИТЬ ИЗ [Таблица] ГДЕ [Условие] — удаляет записи.

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

Как передать результат запроса в отчёт?

Используйте метод Выгрузить() для преобразования результата в таблицу значений:

РезультатЗапроса = Запрос.Выполнить();

ТаблицаДанных = РезультатЗапроса.Выгрузить();

Отчет.СхемаКомпоновкиДанных.Настройки.ИсточникДанных = Новый ИсточникДанныхТаблицаЗначений(ТаблицаДанных);