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

В этой статье мы разберём все способы добавления полей в запросы: от элементарного указания колонок в операторе ВЫБРАТЬ до работы с виртуальными таблицами, объединениями и подзапросами. Особое внимание уделим типичным ошибкам, которые приводят к падению производительности или некорректным результатам. Материал будет полезен как новичкам, которые только осваивают 1С 8.3, так и опытным программистам, ищущим нестандартные решения.

Прежде чем переходить к практике, убедитесь, что у вас есть доступ к конфигуратору 1С с правами на редактирование объектов. Все примеры кода протестированы на платформе 1С:Предприятие 8.3.20, но подходят и для более ранних версий (начиная с 8.2). Если вы работаете с управляемыми формами или обычными формами, принципы добавления полей остаются идентичными — различаться будут только способы вызова запроса.

1. Базовый синтаксис: как добавить поле в простой запрос

Начнём с самого простого — добавления поля в запрос типа ВЫБРАТЬ. Предположим, у вас есть запрос, который выбирает только Наименование и Цена из справочника Номенклатура, а теперь требуется добавить поле Артикул.

Исходный запрос:

ВЫБРАТЬ

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

Номенклатура.Цена КАК Цена

ИЗ

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

Модифицированный запрос с добавленным полем:

ВЫБРАТЬ

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

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

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

ИЗ

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

  • 📌 Правило 1: Поля перечисляются через запятую после оператора ВЫБРАТЬ. Порядок важен — он определяет последовательность колонок в результате.
  • 🔄 Правило 2: Для каждого поля можно указать псевдоним (после КАК). Если псевдоним не указан, будет использоваться оригинальное имя поля.
  • ⚠️ Ограничение: Нельзя добавлять поля, которых нет в исходной таблице (например, Номенклатура.НесуществующееПоле вызовет ошибку).

Если поле является сложным типом (например, РеквизитТабличнойЧасти), его нужно указывать с точкой через родительский объект. Пример для документа ЗаказПокупателя:

ВЫБРАТЬ

Заказ.Номер КАК Номер,

Заказ.Дата КАК Дата,

Заказ.Товары.Номенклатура КАК Номенклатура // Поле из табличной части

ИЗ

Документ.ЗаказПокупателя КАК Заказ

💡

Если вы добавляете поле из табличной части, но не указываете условие соединения (например, ЛЕВОЕ СОЕДИНЕНИЕ), в результате могут появиться дублирующиеся строки. Всегда проверяйте количество записей в выборке после модификации запроса.

2. Добавление вычисляемых полей и агрегатных функций

Часто требуется не просто вывести поле из базы, а создать вычисляемое поле — например, рассчитать сумму с учётом скидки или привести дату к определённому формату. Для этого используются агрегатные функции (СУММА, КОЛИЧЕСТВО) и выражения.

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

ВЫБРАТЬ

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

СтрокиЗаказа.Цена КАК Цена,

СтрокиЗаказа.Количество КАК Количество,

СтрокиЗаказа.Цена СтрокиЗаказа.Количество (1 - СтрокиЗаказа.Скидка/100) КАК СуммаСоСкидкой

ИЗ

Документ.ЗаказПокупателя.Товары КАК СтрокиЗаказа

Агрегатные функции позволяют группировать данные. Например, добавим поле с ИТОГО по номенклатуре:

ВЫБРАТЬ

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

СУММА(СтрокиЗаказа.Количество) КАК ОбщееКоличество

ИЗ

Документ.ЗаказПокупателя.Товары КАК СтрокиЗаказа

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

СтрокиЗаказа.Номенклатура

Функция Описание Пример использования
СУММА() Суммирует значения по группе СУММА(СтрокиЗаказа.Сумма)
КОЛИЧЕСТВО() Считает количество строк в группе КОЛИЧЕСТВО(ДISTINCT СтрокиЗаказа.Номенклатура)
МАКСИМУМ()/МИНИМУМ() Находит максимальное/минимальное значение МАКСИМУМ(Документы.Дата)
ВЫРАЗИТЬ() Преобразует тип данных ВЫРАЗИТЬ(Дата КАК СТРОКА)

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

📊 Как часто вы используете агрегатные функции в запросах 1С?
Постоянно
Иногда
Редеко
Никогда

3. Работа с виртуальными таблицами: добавление полей из регистров

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

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

ВЫБРАТЬ

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

ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток

ИЗ

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

  • 🔗 Особенность 1: Виртуальные таблицы требуют указания параметров (например, даты в примере выше). Без них запрос не выполнится.
  • 📅 Особенность 2: Для регистров бухгалтерии можно использовать виртуальные таблицы Обороты(), ОстаткиИОбороты().
  • ⚠️ Предупреждение: Добавление полей из виртуальных таблиц может значительно замедлить запрос, если не использовать индексируемые отборы.

Если нужно добавить поле из ресурса регистра, его имя указывается без префикса. Например, для регистра Продажи с ресурсом СуммаПродаж:

ВЫБРАТЬ

ПродажиОбороты.Номенклатура КАК Номенклатура,

ПродажиОбороты.СуммаПродаж КАК Сумма // Ресурс регистра

ИЗ

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

Что будет, если не указать параметры в виртуальной таблице?

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

4. Добавление полей через соединения (JOIN)

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

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

ВЫБРАТЬ

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

Поставщики.Наименование КАК Поставщик

ИЗ

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

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

ПО Номенклатура.ОсновнойПоставщик = Поставщики.Ссылка

Типы соединений и их особенности:

  • 🔗 ВНУТРЕННЕЕ СОЕДИНЕНИЕ — возвращает только строки, где есть совпадение в обеих таблицах.
  • 🔘 ЛЕВОЕ СОЕДИНЕНИЕ — возвращает все строки из левой таблицы, даже если нет совпадений в правой (для отсутствующих полей будет NULL).
  • 🔚 ПОЛНОЕ СОЕДИНЕНИЕ — возвращает все строки из обеих таблиц, заполняя NULL при отсутствии совпадений.
⚠️ Внимание: При использовании ЛЕВОГО СОЕДИНЕНИЯ с виртуальными таблицами регистров может произойти декартово произведение, если не указаны корректные условия соединения. Например, соединение документа РеализацияТоваровУслуг с виртуальной таблицей Остатки() без отбора по складу или номенклатуре приведёт к экспоненциальному росту строк в результате.

Если нужно добавить поле из подчинённого объекта (например, реквизита справочника, который сам является справочником), используйте цепочку соединений:

ВЫБРАТЬ

Заказы.Номер КАК Номер,

Города.Наименование КАК ГородПоставки

ИЗ

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

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

ПО Заказы.Контрагент = Клиенты.Ссылка

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

ПО Клиенты.Город = Города.Ссылка

Указан ли тип соединения (ВНУТРЕННЕЕ, ЛЕВОЕ и т.д.)?

Есть ли условие ПО для соединения?

Не приводит ли соединение к декартову произведению?

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

-->

5. Добавление полей через подзапросы

Подзапросы позволяют добавлять поля, значения которых рассчитываются на основе другой выборки. Это полезно, когда нужно получить агрегированные данные для каждой строки основного запроса.

Пример: добавим поле ПоследняяЦенаПоставки, которое будет содержать цену из последнего документа ПоступлениеТоваров для каждой номенклатуры:

ВЫБРАТЬ

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

(

ВЫБРАТЬ ПЕРВЫЕ 1

Поступления.Цена КАК ПоследняяЦена

ИЗ

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

ГДЕ

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

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

Поступления.Дата УБЫВ, Поступления.Время УБЫВ

) КАК ПоследняяЦенаПоставки

ИЗ

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

Особенности работы с подзапросами:

  • 🔍 Подзапрос должен возвращать одно значение (или NULL). Если подзапрос вернёт несколько строк, основной запрос завершится с ошибкой.
  • ⚡ Для оптимизации используйте ПЕРВЫЕ N или условия отбора внутри подзапроса.
  • 🔄 Подзапросы можно использовать не только в ВЫБРАТЬ, но и в ГДЕ или ИМЕЮЩИЕ.

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

ВЫБРАТЬ

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

ВЫБОР

КОГДА ЕСТЬNULL(

ВЫБРАТЬ 1

ИЗ Документ.ЗаказПокупателя КАК Заказы

ГДЕ Заказы.Контрагент = Клиенты.Ссылка

), 1, 0

КАК ЕстьЗаказы

ИЗ

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

⚠️ Внимание: Подзапросы в ВЫБРАТЬ выполняются для каждой строки основного запроса, что может значительно замедлить работу. Если возможно, замените подзапрос на соединение или используйте временные таблицы.

6. Добавление полей в запросы с ИТОГАМИ и группировкой

При работе с ИТОГАМИ или ГРУППИРОВКА добавление полей требует особого подхода. Нельзя просто добавить поле в выборку — оно должно быть либо агрегировано, либо включено в группировку.

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

ВЫБРАТЬ

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

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

СУММА(Продажи.Количество) КАК ОбщееКоличество

ИЗ

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

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

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

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

Номенклатура.Категория,

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

Если нужно добавить поле, которое не участвует в группировке, но должно быть агрегировано, используйте функции:

ВЫБРАТЬ

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

МАКСИМУМ(Номенклатура.Артикул) КАК Артикул, // Берём любой артикул из группы

СУММА(Продажи.Сумма) КАК ОбщаяСумма

ИЗ ...

СГРУППИРОВАТЬ ПО Номенклатура.Категория

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

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

7. Оптимизация запросов после добавления полей

Добавление новых полей в запрос может привести к ухудшению производительности, особенно если:

  • 🐢 Поле берётся из несвязанной таблицы (например, через ЛЕВОЕ СОЕДИНЕНИЕ без индексов).
  • 🔄 Поле является вычисляемым и требует ресурсоёмких операций (например, ПОДСТРОКА или ВЫРАЗИТЬ).
  • 📊 Поле добавляется из виртуальной таблицы с большим периодом.

Способы оптимизации:

  1. Используйте индексируемые поля в условиях соединения. Например, вместо ПО Контрагент.Наименование = "ООО Ромашка" лучше использовать ПО Контрагент.Ссылка = &СсылкаНаКонтрагента.
  2. Ограничивайте периоды для виртуальных таблиц. Вместо Обороты(НачалоГода(), КонецГода()) используйте Обороты(&НачалоПериода, &КонецПериода) с явной передачей дат.
  3. Заменяйте подзапросы на соединения, где это возможно. Подзапросы в цикле (например, в ДЛЯ ИЗМЕНЕНИЯ) могут тормозить в 10–100 раз сильнее.
  4. Используйте временные таблицы для сложных расчётов. Это позволит разделить запрос на этапы и избежать повторных вычислений.

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

// Исходный запрос (медленный)

ВЫБРАТЬ

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

(

ВЫБРАТЬ СУММА(Остатки.КоличествоОстаток)

ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(ТекущаяДата(), ) КАК Остатки

ГДЕ Остатки.Номенклатура = Номенклатура.Ссылка

) КАК Остаток

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

// Оптимизированный вариант

ВЫБРАТЬ

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

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

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(ТекущаяДата(), ) КАК ОстаткиНоменклатуры

ПО Номенклатура.Ссылка = ОстаткиНоменклатуры.Номенклатура

⚠️ Внимание: Если после добавления поля запрос стал выполняться дольше 5 секунд, проверьте план выполнения в консоли запросов 1С (кнопка "Показать план"). Часто причина тормозов — отсутствие индексов на полях, используемых в условиях ГДЕ или ПО.
💡

Добавление поля в запрос всегда должно сопровождаться проверкой производительности. Даже "невинное" поле из справочника может вызвать полное сканирование таблицы, если оно не проиндексировано.

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

Ошибка 1: Опечатка в имени поля

Симптомы: запрос не выполняется, ошибка "Поле не найдено".

Решение: всегда проверяйте имена полей в конфигураторе 1С (раздел "Метаданные"). Например, поле Код в справочнике может называться Артикул или Штрихкод в зависимости от конфигурации.

Ошибка 2: Добавление поля без учёта прав доступа

Симптомы: запрос выполняется, но поле пустое (NULL) для некоторых пользователей.

Решение: проверьте права ролей на чтение добавляемого поля (раздел "Администрирование" → "Пользователи и права").

Ошибка 3: Использование неиндексируемых полей в условиях

Симптомы: запрос стал выполняться в 10–100 раз медленнее.

Решение: замените условие на индексируемое поле (например, вместо ПО Наименование используйте ПО Ссылка).

Ошибка 4: Добавление поля из несоединённой таблицы

Симптомы: декартово произведение (количество строк в результате умножается).

Решение: добавьте условие соединения (ЛЕВОЕ СОЕДИНЕНИЕ ... ПО) или используйте подзапрос.

Ошибка 5: Неучтённые NULL-значения

Симптомы: некорректные итоги или пропущенные строки в результате.

Решение: используйте ВЫРАЗИТЬ(NULL КАК Число(10,2)) или ЕСТЬNULL(Поле, 0) для замены пустых значений.

Как найти все поля справочника или документа?

В конфигураторе 1С откройте нужный объект (например, справочник Номенклатура), перейдите на вкладку "Данные" и разверните список реквизитов. Для табличных частей поля отображаются в соответствующих разделах. Альтернативно можно использовать синтакс-помощник в редакторе запросов (кнопка F2).

FAQ: Частые вопросы по добавлению полей в запросах 1С

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

Да, если запрос формируется динамически (например, через ТекстЗапроса = Новый Запрос;), вы можете модифицировать строку запроса программно. Пример:

ТекстЗапроса = Новый Запрос;

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

"ВЫБРАТЬ

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

Номенклатура.Цена КАК Цена

ИЗ

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

// Добавляем поле программно

Если НужноДобавитьАртикул Тогда

ТекстЗапроса.Текст = СтрЗаменить(ТекстЗапроса.Текст, "Цена КАК Цена", "Цена КАК Цена, Номенклатура.Артикул КАК Артикул");

КонецЕсли;

Однако такой подход требует аккуратности, чтобы не нарушить синтаксис запроса.

Как добавить поле из другой базы данных (распределённой инфобазы)?

Для работы с распределёнными базами используйте планы обмена или WS-сервисы. Прямое добавление полей из другой базы в запрос невозможно. Альтернативные варианты:

  1. Создать реплицируемый справочник и добавлять поле из него.
  2. Использовать HTTPСервис для получения данных из другой базы и объединять результаты в коде.

Пример запроса к WS-сервису:

HTTPСоединение = Новый HTTPСоединение("http://server/ws/");

HTTPЗапрос = Новый HTTPЗапрос("/GetNomenclatureData");

Ответ = HTTPСоединение.Получить(HTTPЗапрос);

Данные = JSON.Прочитать(Ответ.ПолучитьТелоКакСтроку());

Почему после добавления поля запрос стал возвращать дубли?

Дубли появляются, если:

  • Вы добавили поле из таблицы, которая имеет отношение "один-ко-многим" с основной таблицей запроса (например, поле из табличной части документа).
  • Не указано условие соединения (ПО) для добавленной таблицы.
  • Используется ПОЛН