Добавление полей в запросах 1С: от простого выбора до соединений и подзапросов
Содержание
Поле добавляют в секцию ВЫБРАТЬ запроса — просто дописывают его имя через запятую после уже перечисленных. Если поле лежит в другой таблице или его нужно вычислить, одной строкой уже не обойтись: подключают соединение, подзапрос или выражение. В языке запросов 1С 8.3 всё это оформляется одними и теми же конструкциями независимо от конфигурации — БП 3.0, ЗУП 3.1, УТ 11 или своя разработка.
Ниже — как добавить поле в запрос во всех типовых случаях: реквизит документа или справочника, вычисляемое значение, агрегат (сумма, количество), данные из регистров через виртуальные таблицы, поля из связанных таблиц через соединение и значение из подзапроса. Текст запроса писать руками необязательно — в Конфигураторе есть конструктор, но понимать структуру всё равно нужно, иначе сложные поля через него не собрать.
Простое поле: дописать реквизит в секцию ВЫБРАТЬ
Самый частый случай — добавить в выборку ещё один реквизит таблицы. Поля перечисляются через запятую, источник данных указывается в секции ИЗ.
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Наименование,
Номенклатура.Артикул
ИЗ
Справочник.Номенклатура КАК Номенклатура
Чтобы добавить, например, единицу измерения, дописываем строку в секцию ВЫБРАТЬ:
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Наименование,
Номенклатура.Артикул,
Номенклатура.ЕдиницаИзмерения
ИЗ
Справочник.Номенклатура КАК Номенклатура
Несколько правил, которые экономят время:
- 🔸 После последнего поля запятая не ставится — лишняя запятая перед
ИЗдаёт ошибку синтаксиса. - 🔸 Обращаться к полю нужно через псевдоним таблицы (
Номенклатура.Артикул), заданный послеКАКв секцииИЗ. - 🔸 Если имя поля или псевдонима содержит пробел либо совпадает с ключевым словом, его не берут в кавычки — просто переименовывают псевдоним.
К реквизиту ссылочного типа можно обращаться «через точку», добавляя поле из связанной таблицы без явного соединения:
ВЫБРАТЬ
Номенклатура.Наименование,
Номенклатура.ЕдиницаИзмерения.Наименование КАК ЕдиницаНаименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
Платформа сама подставит левое соединение со справочником единиц. Это удобно для двух-трёх уровней вложенности, но на больших выборках цепочки «через точку» лучше заменять явным соединением — так предсказуемее план запроса.
Псевдоним через КАК задают, чтобы поле попало в результат под понятным именем — особенно для вычисляемых значений и колонок отчёта на СКД.
Вычисляемые поля и выражения
Вычисляемое поле — это не реквизит, а выражение в секции ВЫБРАТЬ. Арифметика, конкатенация строк, функции работы с датами, условная логика.
ВЫБРАТЬ
Товары.Номенклатура,
Товары.Количество,
Товары.Цена,
Товары.Количество * Товары.Цена КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
Поле Сумма в таблице не хранится — оно считается на лету. Псевдоним здесь обязателен: без КАК платформа не сможет назвать колонку.
Для условий внутри поля используют конструкцию ВЫБОР … КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ (аналог CASE в SQL):
ВЫБРАТЬ
Контрагенты.Наименование,
ВЫБОР
КОГДА Контрагенты.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ФизическоеЛицо)
ТОГДА "Физлицо"
ИНАЧЕ "Организация"
КОНЕЦ КАК ТипКонтрагента
ИЗ
Справочник.Контрагенты КАК Контрагенты
Ссылку на конкретный элемент перечисления, предопределённый элемент справочника или пустую ссылку задают функцией ЗНАЧЕНИЕ(...). Сравнивать поле с «текстом» названия нельзя — только со значением нужного типа.
Строковые поля склеивают оператором +, даты обрабатывают функциями НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ДОБАВИТЬКДАТЕ, РАЗНОСТЬДАТ. Для чисел пригодятся ВЫРАЗИТЬ(... КАК ЧИСЛО(15,2)), ОКРУГЛ.
Агрегатные поля: сумма, количество, максимум
Когда нужно свернуть строки — получить итог по группе — добавляют агрегатную функцию: СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ.
ВЫБРАТЬ
Товары.Номенклатура,
СУММА(Товары.Количество) КАК Количество,
СУММА(Товары.Количество * Товары.Цена) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
Главное правило: если в запросе есть хоть одно агрегатное поле, все остальные поля из секции ВЫБРАТЬ обязаны попасть в секцию СГРУППИРОВАТЬ ПО. Иначе платформа выдаст ошибку о том, что поле не входит в группировку.
КОЛИЧЕСТВО(*) считает все строки, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) — только уникальные значения. Это разные числа, и путаница между ними — частая причина расхождений в отчётах.
Поля из регистров через виртуальные таблицы
Остатки и обороты не хранятся готовыми числами — их возвращают виртуальные таблицы регистров. Чтобы добавить в запрос поле остатка или оборота, обращаются не к самому регистру, а к его виртуальной таблице.
Для регистра накопления:
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.Склад,
Остатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
Имя ресурса в виртуальной таблице остатков получает суффикс Остаток (КоличествоОстаток), в таблице оборотов — Приход, Расход, Оборот. Тип виртуальной таблицы выбирают по задаче:
| Таблица | Что возвращает | Параметры |
|---|---|---|
Остатки(Период, Условие) | остаток на момент | период расчёта |
Обороты(Начало, Конец, Период, Условие) | приход/расход за интервал | границы и периодичность |
ОстаткиИОбороты(...) | остатки на начало/конец плюс обороты | границы и периодичность |
Отбор задавайте в параметрах виртуальной таблицы (второй параметр — условие), а не в секции ГДЕ. Условие внутри таблицы отсекает лишние данные до расчёта итогов, а ГДЕ — уже после, и на больших регистрах разница в скорости кратная.
Для регистра сведений с периодичностью добавляют поля через срез:
ВЫБРАТЬ
Цены.Номенклатура,
Цены.Цена,
Цены.Валюта
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК Цены
СрезПоследних даёт актуальные записи на дату, СрезПервых — самые ранние. Для непериодического регистра сведений обращаются прямо к таблице РегистрСведений.Имя без среза.
Поля из связанных таблиц через соединение
Когда поле лежит в другой таблице, которую не достать «через точку» (например, значение из другого документа или регистра), добавляют соединение СОЕДИНЕНИЕ … ПО.
ВЫБРАТЬ
Заказы.Ссылка,
Заказы.Контрагент,
Оплаты.СуммаОплаты
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ВзаиморасчётыСКлиентами.Обороты КАК Оплаты
ПО Оплаты.ЗаказПокупателя = Заказы.Ссылка
Виды соединений:
- 🔹
ЛЕВОЕ СОЕДИНЕНИЕ— берём все строки левой таблицы; где справа совпадения нет, добавленное поле получитNULL. - 🔹
ВНУТРЕННЕЕ СОЕДИНЕНИЕ— только строки, где есть совпадение в обеих таблицах. - 🔹
ПРАВОЕ СОЕДИНЕНИЕ— зеркало левого. - 🔹
ПОЛНОЕ СОЕДИНЕНИЕ— все строки из обеих таблиц.
В 95% отчётов используют именно левое соединение: нужны все строки основной таблицы, а добавленное поле — дополнение к ним.
После левого соединения поле может оказаться пустым (NULL), и в арифметике это ломает результат: NULL + 100 даёт NULL, а не 100. Поэтому числовые поля из присоединённой таблицы оборачивают в ЕСТЬNULL:
ВЫБРАТЬ
Заказы.Ссылка,
ЕСТЬNULL(Оплаты.СуммаОплаты, 0) КАК Оплачено
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ВзаиморасчётыСКлиентами.Обороты КАК Оплаты
ПО Оплаты.ЗаказПокупателя = Заказы.Ссылка
ЕСТЬNULL(Поле, ЗначениеПоУмолчанию) заменяет пустое значение на ноль, пустую строку или пустую дату — в зависимости от типа.
Поле-значение из подзапроса
Иногда поле нужно получить отдельным запросом внутри запроса. Подзапрос добавляют в трёх местах: как источник в ИЗ, как фильтр в ГДЕ и реже — как скалярное поле.
Чаще всего подзапрос ставят источником и соединяют с ним, предварительно свернув данные:
ВЫБРАТЬ
Номенклатура.Ссылка,
ЕСТЬNULL(Продажи.Количество, 0) КАК Продано
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Товары.Номенклатура КАК Номенклатура,
СУММА(Товары.Количество) КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
) КАК Продажи
ПО Продажи.Номенклатура = Номенклатура.Ссылка
Так добавляем к каждой номенклатуре поле «продано всего», уже агрегированное внутри подзапроса. В секции ГДЕ подзапрос применяют с оператором В:
ГДЕ
Номенклатура.Ссылка В (
ВЫБРАТЬ РАЗЛИЧНЫЕ Товары.Номенклатура
ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Товары
)
На повторяющихся расчётах подзапрос лучше вынести в отдельную временную таблицу пакетного запроса (ПОМЕСТИТЬ ВременнаяТаблица) и проиндексировать поле соединения. Тогда платформа посчитает его один раз, а не на каждую строку.
Поля в запросах с итогами и группировкой
Группировка (СГРУППИРОВАТЬ ПО) сворачивает строки, а итоги (ИТОГИ … ПО) добавляют в результат отдельные строки с подытогами — это разные механизмы.
ВЫБРАТЬ
Товары.Склад,
Товары.Номенклатура,
СУММА(Товары.Количество) КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Склад,
Товары.Номенклатура
ИТОГИ
СУММА(Количество)
ПО
Склад
Секция ИТОГИ добавляет строки с суммой по каждому складу и общий итог. Обращаться к результату с итогами удобнее через обход по группировкам: Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам).
Если нужно добавить поле, которое участвует только в упорядочивании, его помещают в УПОРЯДОЧИТЬ ПО. При группировке сортировать можно по полям группировки или по агрегатам.
Конструктор запроса в Конфигураторе
Текст запроса необязательно набирать вручную. В модуле ставим курсор внутрь строки с текстом запроса, правой кнопкой мыши вызываем контекстное меню и выбираем Конструктор запроса. Если текста ещё нет — конструктор предложит создать новый.
Чтобы добавить поле через конструктор:
- На вкладке
Таблицы и поляслева выбираем таблицу-источник. - В средней колонке раскрываем её поля и двойным кликом переносим нужное в правую колонку
Поля. - Для вычисляемого поля жмём кнопку добавления произвольного выражения над списком полей и пишем формулу.
- Псевдоним задаём на вкладке
Объединения/Псевдонимы.
Соединения настраиваются на вкладке Связи, группировка — на Группировке, итоги — на вкладке Итоги. Конструктор удобен для сборки каркаса, а тонкую правку выражений и виртуальных таблиц почти всегда быстрее дописать руками.
Для отладки готового запроса вне модуля используют обработку «Консоль запросов» — внешнюю обработку
, которую подключают через Файл → Открыть. Она показывает результат и план, не трогая код конфигурации.
Оптимизация запроса после добавления полей
Каждое новое поле — особенно из соединения или подзапроса — нагружает запрос. Несколько приёмов, которые держат его быстрым:
- ⚡ Не выбирайте лишнего.
ВЫБРАТЬ *в языке запросов не поддерживается, и это к лучшему: перечисляйте только нужные поля. - ⚡ Отбор в виртуальных таблицах задавайте параметром, а не в
ГДЕ. - ⚡ Избегайте соединения с виртуальной таблицей напрямую — сначала поместите её данные во временную таблицу пакетного запроса, затем соединяйте и индексируйте поле связи (
ИНДЕКСИРОВАТЬ ПО). - ⚡ Не обращайтесь «через точку» на много уровней в больших выборках — заменяйте явным соединением.
- ⚡ Не соединяйте по полям составного (неопределённого) типа — платформа не использует индекс.
Частые ошибки при добавлении полей
- ❌ Поле не входит в группировку. Добавили агрегат, но не внесли остальные поля в
СГРУППИРОВАТЬ ПО. Решение — перечислить там все неагрегатные поля. - ❌ NULL вместо числа. После левого соединения поле пустое, и сумма «съедается». Оборачивайте такие поля в
ЕСТЬNULL(Поле, 0). - ❌ Остаток не на ту дату. Период передали в
ГДЕ, а не в параметр виртуальной таблицыОстатки. Отбор по дате вГДЕвиртуальная таблица уже не учитывает при расчёте остатка. - ❌ Сравнение перечисления со строкой. Поле-перечисление сравнивают с текстом названия. Нужна функция
ЗНАЧЕНИЕ(Перечисление.Имя.Значение). - ❌ Дубли строк после соединения. Присоединённая таблица содержит несколько записей на одну строку основной — получаем задвоение. Сверните подзапрос агрегатом до соединения.
Частые вопросы
Можно ли добавить поле, которого нет в таблице?
ВЫБРАТЬ и задаёте псевдоним через КАК. В таблице такое поле не хранится, оно считается при выполнении запроса.Почему добавленное поле возвращает NULL?
ЕСТЬNULL(Поле, 0) для чисел или ЕСТЬNULL(Поле, "") для строк. Для даты — ЕСТЬNULL(Поле, ДАТАВРЕМЯ(1,1,1)).Как добавить в запрос поле остатка по складу?
РегистрНакопления.Имя.Остатки(&Период, Склад = &Склад). Ресурс получит суффикс Остаток, например КоличествоОстаток.В чём разница между СГРУППИРОВАТЬ ПО и ИТОГИ?
СГРУППИРОВАТЬ ПО сворачивает строки в одну по значению поля. ИТОГИ … ПО оставляет детальные строки и добавляет к ним отдельные строки-подытоги. Их можно использовать вместе.Как добавить поле из другого документа?
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Имя КАК Алиас ПО условие или через подзапрос в секции ИЗ. Напрямую «через точку» доступны только реквизиты ссылочных полей текущей таблицы.