Язык запросов 1С с нуля: первый ВЫБРАТЬ, параметры, временные таблицы и пакеты
Содержание
Чтобы сделать запрос в 1С, создайте объект Новый Запрос, запишите в свойство Текст инструкцию ВЫБРАТЬ … ИЗ …, передайте значения через УстановитьПараметр() и вызовите Выполнить(). Текст удобно собрать мышью в конструкторе запроса Конфигуратора, а потом поправить руками.
Типичная ситуация: главбух просит «список покупателей с суммой отгрузок за месяц, от больших к меньшим». Стандартного отчёта с такой раскладкой нет, а выгружать в Excel и сводить вручную каждый месяц надоедает. Десять строк на языке запросов решают задачу один раз.
Что такое запрос в 1С и где он выполняется
Запрос — это способ прочитать данные из базы одной командой, а не перебирать объекты по одному. Язык похож на SQL, но работает с объектами конфигурации: справочниками, документами, регистрами. Вы пишете Документ.РеализацияТоваровУслуг, а платформа сама находит нужные таблицы в СУБД.
Что важно знать до первой строки кода:
- 📖 Запрос только читает. Изменить или удалить данные через язык запросов 1С нельзя — для этого есть объектная модель.
- 🖥️ Объект
Запросдоступен на сервере, в толстом клиенте и во внешнем соединении. В тонком клиенте его нет, поэтому в управляемой форме код запроса пишут в процедуре с директивой&НаСервере. - 🔒 Запрос по умолчанию учитывает права пользователя и ограничения доступа на уровне записей, если они настроены. Пользователь не увидит в результате то, что ему запрещено.
- 📦 Результат возвращается одним пакетом с сервера СУБД. Это быстрее, чем обращение к реквизитам объекта в цикле.
Конструктор запроса или ручной ввод: что выбрать
Оба способа дают один и тот же текст. Разница — в скорости и контроле.
| Способ | Когда удобен | Слабые места |
|---|---|---|
| Конструктор запроса | Первые шаги, незнакомая структура регистров, сложные соединения | Иногда добавляет лишние поля и псевдонимы, неудобен для динамической сборки текста |
| Ручной ввод | Короткие запросы, правка готового текста, сборка условий в коде | Опечатки в именах полей видны только при выполнении |
| Комбинация | Почти всегда: каркас в конструкторе, доводка руками | — |
Как открыть конструктор запроса
- Откройте модуль формы или обработки в Конфигураторе.
- Поставьте курсор в пустое место процедуры.
- Щёлкните правой кнопкой и выберите «Конструктор запроса…». Есть вариант «Конструктор запроса с обработкой результата» — он сразу допишет
Запрос = Новый Запрос, выполнение и цикл обхода. - На вкладке «Таблицы и поля» выберите источник слева и перетащите нужные поля вправо.
- Остальные вкладки — «Связи», «Группировка», «Условия», «Порядок», «Пакет запросов» — заполняйте по мере надобности.
- Нажмите «ОК»: текст вставится в модуль строкой с символами
|в начале каждой строки.
💡 Чтобы поправить готовый запрос конструктором, поставьте курсор внутрь его текста и снова вызовите конструктор. Он разберёт текст и откроет его на вкладках.
Где проверить запрос без программирования
Для отладки удобна внешняя обработка «Консоль запросов». В ней пишут текст, задают параметры и сразу видят таблицу результата. Это быстрее, чем каждый раз запускать свою обработку. Консоль открывают в режиме 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С
Медленный запрос почти всегда тормозит по одной из этих причин.
- Запрос в цикле. Сто итераций — сто обращений к СУБД. Соберите все значения в массив и выполните один запрос с
В (&Список). - Обращение «через точку» к составному полю.
Движения.Регистратор.Датазаставляет платформу соединить таблицу со всеми документами, которые могут быть регистратором. Если тип известен, приведите его:ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата. - Отбор в ГДЕ вместо параметров виртуальной таблицы. Разобран в примере 2.
- ИЛИ в условии соединения. Замените двумя запросами через
ОБЪЕДИНИТЬ ВСЕ. - Лишние поля. Выбирайте только то, что выводите.
ПЕРВЫЕ Nпомогает, когда нужна пара строк для проверки. - Соединение с подзапросом без индекса. Вынесите подзапрос во временную таблицу с
ИНДЕКСИРОВАТЬ ПО. ПОДОБНО "%текст%". Поиск с процентом в начале не использует индекс. Если можно, ищите по началу строки.
Как найти узкое место: в Конфигураторе запустите отладку и включите Отладка → Замер производительности. Замер покажет, какие строки кода съели больше всего времени. Если это Выполнить() — дело в тексте запроса.
| Приём | Когда помогает | Риск |
|---|---|---|
| Параметры виртуальной таблицы | Остатки и обороты по части измерений | Нет |
ВЫРАЗИТЬ для составного поля | Поле «Регистратор», «Документ основания» | Строки другого типа дадут NULL |
| Временная таблица с индексом | Соединение больших выборок | Лишний шаг для маленьких таблиц |
ОБЪЕДИНИТЬ ВСЕ вместо ИЛИ | Сложные условия соединения | Возможны дубли, если условия пересекаются |
Частые ошибки в запросах 1С и как их не допустить
Документ.РеализацияТоваровУслуг.Товары.УстановитьПараметр() совпадает с &Имя в тексте символ в символ.NULL. Оберните поле в ЕСТЬNULL(Поле, 0).ВЫРАЗИТЬ(Т.Комментарий КАК Строка(200)).Проведен для документов или НЕ ПометкаУдаления для справочников.ПРИВИЛЕГИРОВАННЫЙ режим без нужды.Проверьте себя
Частые вопросы
Можно ли запросом изменить или удалить данные в 1С?
Чем запрос отличается от отчёта на СКД?
Почему в тонком клиенте пишет, что тип Запрос не определён?
Запрос недоступен на клиенте. Вынесите код в процедуру с директивой &НаСервере или &НаСервереБезКонтекста.Можно ли писать запросы на английском?
SELECT, FROM, WHERE и другие англоязычные ключевые слова. Имена объектов конфигурации при этом остаются такими, как в дереве метаданных.Как посмотреть текст запроса, собранного в коде?
Запрос.Текст. Текст можно скопировать в консоль запросов и выполнить там с теми же параметрами.