Язык запросов 1С с нуля: первый ВЫБРАТЬ, параметры, временные таблицы и пакеты

· 10 мин

Содержание

Чтобы сделать запрос в 1С, создайте объект Новый Запрос, запишите в свойство Текст инструкцию ВЫБРАТЬ … ИЗ …, передайте значения через УстановитьПараметр() и вызовите Выполнить(). Текст удобно собрать мышью в конструкторе запроса Конфигуратора, а потом поправить руками.

Типичная ситуация: главбух просит «список покупателей с суммой отгрузок за месяц, от больших к меньшим». Стандартного отчёта с такой раскладкой нет, а выгружать в Excel и сводить вручную каждый месяц надоедает. Десять строк на языке запросов решают задачу один раз.

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

Запрос — это способ прочитать данные из базы одной командой, а не перебирать объекты по одному. Язык похож на SQL, но работает с объектами конфигурации: справочниками, документами, регистрами. Вы пишете Документ.РеализацияТоваровУслуг, а платформа сама находит нужные таблицы в СУБД.

Что важно знать до первой строки кода:

  • 📖 Запрос только читает. Изменить или удалить данные через язык запросов 1С нельзя — для этого есть объектная модель.
  • 🖥️ Объект Запрос доступен на сервере, в толстом клиенте и во внешнем соединении. В тонком клиенте его нет, поэтому в управляемой форме код запроса пишут в процедуре с директивой &НаСервере.
  • 🔒 Запрос по умолчанию учитывает права пользователя и ограничения доступа на уровне записей, если они настроены. Пользователь не увидит в результате то, что ему запрещено.
  • 📦 Результат возвращается одним пакетом с сервера СУБД. Это быстрее, чем обращение к реквизитам объекта в цикле.

Конструктор запроса или ручной ввод: что выбрать

Оба способа дают один и тот же текст. Разница — в скорости и контроле.

СпособКогда удобенСлабые места
Конструктор запросаПервые шаги, незнакомая структура регистров, сложные соединенияИногда добавляет лишние поля и псевдонимы, неудобен для динамической сборки текста
Ручной вводКороткие запросы, правка готового текста, сборка условий в кодеОпечатки в именах полей видны только при выполнении
КомбинацияПочти всегда: каркас в конструкторе, доводка руками—

Как открыть конструктор запроса

  1. Откройте модуль формы или обработки в Конфигураторе.
  2. Поставьте курсор в пустое место процедуры.
  3. Щёлкните правой кнопкой и выберите «Конструктор запроса…». Есть вариант «Конструктор запроса с обработкой результата» — он сразу допишет Запрос = Новый Запрос, выполнение и цикл обхода.
  4. На вкладке «Таблицы и поля» выберите источник слева и перетащите нужные поля вправо.
  5. Остальные вкладки — «Связи», «Группировка», «Условия», «Порядок», «Пакет запросов» — заполняйте по мере надобности.
  6. Нажмите «ОК»: текст вставится в модуль строкой с символами | в начале каждой строки.

💡 Чтобы поправить готовый запрос конструктором, поставьте курсор внутрь его текста и снова вызовите конструктор. Он разберёт текст и откроет его на вкладках.

Где проверить запрос без программирования

Для отладки удобна внешняя обработка «Консоль запросов». В ней пишут текст, задают параметры и сразу видят таблицу результата. Это быстрее, чем каждый раз запускать свою обработку. Консоль открывают в режиме 1С:Предприятие через Файл → Открыть, если у пользователя есть право открывать внешние обработки.

Структура запроса 1С: из каких частей он состоит

Полный запрос выглядит так. Обязательны только ВЫБРАТЬ и (почти всегда) ИЗ, остальное добавляют по задаче.

ВЫБРАТЬ [РАЗЛИЧНЫЕ] [ПЕРВЫЕ 10]
	Поле1 КАК Псевдоним1,
	Поле2
ИЗ
	Источник КАК Т
	ЛЕВОЕ СОЕДИНЕНИЕ ДругойИсточник КАК Д
	ПО Т.Ссылка = Д.Владелец
ГДЕ
	условие
СГРУППИРОВАТЬ ПО
	Поле1
ИМЕЮЩИЕ
	условие на агрегат
УПОРЯДОЧИТЬ ПО
	Поле1 УБЫВ
ИТОГИ ПО
	Поле1

Что делает каждая часть:

  • 🔹 ВЫБРАТЬ — список полей результата. РАЗЛИЧНЫЕ убирает повторяющиеся строки, ПЕРВЫЕ N ограничивает их число.
  • 🔹 ИЗ — источник: таблица справочника, документа, его табличной части, регистра или виртуальная таблица регистра.
  • 🔹 СОЕДИНЕНИЕ … ПО — связь с другой таблицей: ЛЕВОЕ, ПРАВОЕ, ВНУТРЕННЕЕ, ПОЛНОЕ.
  • 🔹 ГДЕ — отбор строк до группировки.
  • 🔹 СГРУППИРОВАТЬ ПО и агрегаты СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ.
  • 🔹 ИМЕЮЩИЕ — отбор уже после группировки, например «сумма больше 100 000».
  • 🔹 УПОРЯДОЧИТЬ ПО — сортировка, УБЫВ — по убыванию.
  • 🔹 ИТОГИ ПО — промежуточные итоги для иерархической выборки.

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

  • ДАТАВРЕМЯ(2025, 1, 1) — дата прямо в тексте;
  • ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) — пустая ссылка;
  • ЗНАЧЕНИЕ(Перечисление.ИмяПеречисления.ИмяЗначения) — значение перечисления (имена смотрите в дереве конфигурации);
  • ЕСТЬNULL(Поле, 0) — замена NULL на ноль;
  • ВЫРАЗИТЬ(Поле КАК Строка(100)) — приведение типа.

Ключевые слова пишут и по-английски (SELECT, FROM, WHERE), регистр букв не важен. Принято писать по-русски заглавными.

Как сделать простой запрос в 1С: три рабочих примера

Пример 1. Продажи по покупателям за месяц

Запрос из вступления. Документ РеализацияТоваровУслуг с реквизитами Контрагент и СуммаДокумента есть и в Бухгалтерии предприятия 3.0, и в Управлении торговлей 11.

&НаСервере
Процедура ВывестиПродажиНаСервере()

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Реализация.Контрагент КАК Контрагент,
	|	СУММА(Реализация.СуммаДокумента) КАК Сумма
	|ИЗ
	|	Документ.РеализацияТоваровУслуг КАК Реализация
	|ГДЕ
	|	Реализация.Проведен
	|	И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
	|СГРУППИРОВАТЬ ПО
	|	Реализация.Контрагент
	|УПОРЯДОЧИТЬ ПО
	|	Сумма УБЫВ";

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

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Сообщить(СтрШаблон("%1: %2", Выборка.Контрагент, Формат(Выборка.Сумма, "ЧДЦ=2")));
	КонецЦикла;

КонецПроцедуры

Условие Реализация.Проведен обязательно: без него в сумму попадут черновики и документы, помеченные на удаление.

Пример 2. Остатки на дату через виртуальную таблицу

Остатки не считают перебором движений. У регистра накопления есть виртуальная таблица Остатки, в параметрах которой задают дату и отбор. Пусть в конфигурации есть регистр ОстаткиТоваров с измерениями Номенклатура, Склад и ресурсом Количество:

ВЫБРАТЬ
	Ост.Номенклатура КАК Номенклатура,
	Ост.КоличествоОстаток КАК Остаток
ИЗ
	РегистрНакопления.ОстаткиТоваров.Остатки(&Дата, Склад = &Склад) КАК Ост
ГДЕ
	Ост.КоличествоОстаток > 0

Имя поля строится как «ресурс + Остаток»: КоличествоОстаток. У таблицы ОстаткиИОбороты есть ещё КоличествоНачальныйОстаток, КоличествоПриход, КоличествоРасход, КоличествоКонечныйОстаток.

Отбор по измерениям ставьте в параметры виртуальной таблицы, а не в ГДЕ — иначе платформа сначала посчитает остатки по всем складам, и только потом отбросит лишнее.

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

Задача: показать всех покупателей, даже тех, кому в периоде ничего не отгружали.

ВЫБРАТЬ
	Контрагенты.Ссылка КАК Контрагент,
	ЕСТЬNULL(Продажи.Сумма, 0) КАК Сумма
ИЗ
	Справочник.Контрагенты КАК Контрагенты
	ЛЕВОЕ СОЕДИНЕНИЕ (
		ВЫБРАТЬ
			Р.Контрагент КАК Контрагент,
			СУММА(Р.СуммаДокумента) КАК Сумма
		ИЗ
			Документ.РеализацияТоваровУслуг КАК Р
		ГДЕ
			Р.Проведен
			И Р.Дата МЕЖДУ &НачалоПериода И &КонецПериода
		СГРУППИРОВАТЬ ПО
			Р.Контрагент) КАК Продажи
	ПО Контрагенты.Ссылка = Продажи.Контрагент
ГДЕ
	НЕ Контрагенты.ЭтоГруппа
	И НЕ Контрагенты.ПометкаУдаления

Без ЕСТЬNULL у покупателей без продаж в колонке будет NULL, а не ноль. Сложение с NULL в коде даст ошибку.

Параметры и динамические запросы в 1С

Почему значения передают параметрами

Значения из кода передают через &ИмяПараметра и УстановитьПараметр(). Не вклеивайте их в текст строкой:

  • ✅ параметр сохраняет тип: дата остаётся датой, ссылка — ссылкой;
  • ✅ один и тот же текст выполняется с разными значениями;
  • ❌ склейка строк ломается на кавычках в наименованиях и открывает дорогу к подмене условия.

Параметр может быть списком. Для условия ГДЕ Т.Склад В (&Склады) передайте массив или список значений:

Склады = Новый Массив;
Склады.Добавить(ОсновнойСклад);
Склады.Добавить(СкладБрака);
Запрос.УстановитьПараметр("Склады", Склады);

Как собрать условие в зависимости от отбора

Пользователь может указать склад, а может оставить поле пустым. Есть два приёма.

Приём 1. Дописать условие в текст. Куски текста берите только из констант в коде, значения — только параметрами:

ТекстЗапроса =
"ВЫБРАТЬ
|	Т.Номенклатура,
|	Т.Склад
|ИЗ
|	РегистрНакопления.ОстаткиТоваров.Остатки(&Дата, ) КАК Т
|ГДЕ
|	ИСТИНА";

Если ЗначениеЗаполнено(Склад) Тогда
	ТекстЗапроса = ТекстЗапроса + "
	|	И Т.Склад = &Склад";
	Запрос.УстановитьПараметр("Склад", Склад);
КонецЕсли;

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

Приём 2. Условие с «выключателем» прямо в тексте:

ГДЕ
	(&Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) ИЛИ Т.Склад = &Склад)

Текст короче, но ИЛИ мешает СУБД использовать индекс. На больших таблицах первый приём работает заметно быстрее.

💡 Для сложной программной сборки есть объект СхемаЗапроса: он разбирает текст в дерево операторов, полей и условий, которое можно менять из кода и снова превращать в текст.

Временные таблицы и пакетные запросы

Когда запрос разрастается до трёх вложенных подзапросов, его трудно читать и отлаживать. Выход — разбить на шаги внутри одного пакета.

Пакет — это несколько запросов в одном тексте через точку с запятой. Промежуточный результат кладут во временную таблицу оператором ПОМЕСТИТЬ, следующий запрос берёт данные из неё:

ВЫБРАТЬ
	Р.Контрагент КАК Контрагент,
	СУММА(Р.СуммаДокумента) КАК Сумма
ПОМЕСТИТЬ ВТ_Продажи
ИЗ
	Документ.РеализацияТоваровУслуг КАК Р
ГДЕ
	Р.Проведен
	И Р.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
	Р.Контрагент
ИНДЕКСИРОВАТЬ ПО
	Контрагент
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ.Контрагент,
	ВТ.Сумма
ИЗ
	ВТ_Продажи КАК ВТ
ГДЕ
	ВТ.Сумма > 100000

Как получить результаты:

МетодЧто возвращает
Запрос.Выполнить()Результат только последнего запроса пакета
Запрос.ВыполнитьПакет()Массив результатов, по одному на каждый запрос пакета
Результат.Выгрузить()Таблицу значений — удобно для передачи дальше или вывода в форму
Результат.Выбрать()Выборку для обхода циклом Пока Выборка.Следующий()
Результат.Пустой()Истина, если строк нет — проверяйте перед обходом

Временная таблица живёт, пока жив объект Запрос. Чтобы использовать её в другом запросе, создайте общий менеджер:

МВТ = Новый МенеджерВременныхТаблиц;
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МВТ;
// ... Запрос1 создаёт ВТ_Продажи ...
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МВТ;
// ... Запрос2 читает ВТ_Продажи ...

Если таблица больше не нужна, удалите её в пакете командой УНИЧТОЖИТЬ ВТ_Продажи — это освобождает память на сервере.

Подзапрос внутри ИЗ или условия В (ВЫБРАТЬ …) тоже допустим, как в примере 3. Для одного простого шага он нормален. Если подзапрос соединяется с другими таблицами, вынесите его во временную таблицу с индексом: план выполнения станет предсказуемее.

Как ускорить запрос в 1С

Медленный запрос почти всегда тормозит по одной из этих причин.

  1. Запрос в цикле. Сто итераций — сто обращений к СУБД. Соберите все значения в массив и выполните один запрос с В (&Список).
  2. Обращение «через точку» к составному полю. Движения.Регистратор.Дата заставляет платформу соединить таблицу со всеми документами, которые могут быть регистратором. Если тип известен, приведите его: ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата.
  3. Отбор в ГДЕ вместо параметров виртуальной таблицы. Разобран в примере 2.
  4. ИЛИ в условии соединения. Замените двумя запросами через ОБЪЕДИНИТЬ ВСЕ.
  5. Лишние поля. Выбирайте только то, что выводите. ПЕРВЫЕ N помогает, когда нужна пара строк для проверки.
  6. Соединение с подзапросом без индекса. Вынесите подзапрос во временную таблицу с ИНДЕКСИРОВАТЬ ПО.
  7. ПОДОБНО "%текст%". Поиск с процентом в начале не использует индекс. Если можно, ищите по началу строки.

Как найти узкое место: в Конфигураторе запустите отладку и включите Отладка → Замер производительности. Замер покажет, какие строки кода съели больше всего времени. Если это Выполнить() — дело в тексте запроса.

ПриёмКогда помогаетРиск
Параметры виртуальной таблицыОстатки и обороты по части измеренийНет
ВЫРАЗИТЬ для составного поляПоле «Регистратор», «Документ основания»Строки другого типа дадут NULL
Временная таблица с индексомСоединение больших выборокЛишний шаг для маленьких таблиц
ОБЪЕДИНИТЬ ВСЕ вместо ИЛИСложные условия соединенияВозможны дубли, если условия пересекаются

Частые ошибки в запросах 1С и как их не допустить

Диагностика: выберите симптом

Проверьте себя

Проверьте себя
Где отбирать по складу, чтобы остатки считались быстрее?
Какой метод вернёт результаты всех запросов пакета?
Что вернёт левое соединение для покупателя без продаж в поле суммы?

Частые вопросы

Можно ли запросом изменить или удалить данные в 1С?
Нет. Язык запросов 1С только читает. Изменения делают через объекты: получают объект по ссылке, меняют реквизит и записывают.
Чем запрос отличается от отчёта на СКД?
СКД использует тот же язык запросов, но добавляет настройки, группировки и оформление без кода. Запрос в модуле нужен, когда данные обрабатываются программно, а не просто выводятся.
Почему в тонком клиенте пишет, что тип Запрос не определён?
Объект Запрос недоступен на клиенте. Вынесите код в процедуру с директивой &НаСервере или &НаСервереБезКонтекста.
Можно ли писать запросы на английском?
Да, платформа понимает SELECT, FROM, WHERE и другие англоязычные ключевые слова. Имена объектов конфигурации при этом остаются такими, как в дереве метаданных.
Как посмотреть текст запроса, собранного в коде?
Остановитесь отладчиком после сборки и посмотрите значение переменной или Запрос.Текст. Текст можно скопировать в консоль запросов и выполнить там с теми же параметрами.