Язык запросов 1С с нуля: что учить, в каком порядке и на чём тренироваться

· 10 мин

Содержание

Чтобы изучить язык запросов 1С, поставьте бесплатную учебную версию платформы, создайте пустую конфигурацию с двумя-тремя справочниками и регистром и пишите запросы руками, проверяя каждый в конструкторе. Базовый уровень (выборка, условия, группировка, соединения) реально освоить за 3–4 недели по часу в день. Виртуальные таблицы регистров и оптимизация займут ещё столько же.

Частое заблуждение: «знаю SQL — значит, знаю запросы 1С». Основа действительно похожа на SQL, но в 1С запрос только читает данные, обращается к объектам конфигурации, а не к таблицам СУБД, и умеет разыменовывать ссылки через точку. Именно эти отличия дают и удобство, и большинство ошибок производительности.

С чего начать изучение языка запросов 1С

Теория без практики здесь почти не работает . Нужна база, в которой вы сами создали объекты и знаете, какие данные в ней лежат.

Что подготовить:

  • 🖥️ Учебная версия платформы 1С:Предприятие 8.3. Распространяется бесплатно, в ней доступен Конфигуратор. Ограничения касаются объёма данных и работы в клиент-серверном режиме, для учёбы они не мешают.
  • 📦 Своя пустая конфигурация. Справочники Номенклатура, Контрагенты, Склады, документ ПоступлениеТоваров с табличной частью и регистр накопления остатков. На таком наборе можно отработать всё.
  • 🔍 Консоль запросов. Внешняя обработка, в которой пишут текст запроса, задают параметры и сразу видят результат. Её версии свободно распространяются, в том числе среди обработок для разработчиков на диске ИТС.
  • 📚 Типовая демо-база (например, Бухгалтерия 3.0 демо) — для второго этапа, когда захочется реальных объёмов и связей.

Примерный план на 6–8 недель:

НеделяЧто изучатьИтог недели
1Структура запроса, ВЫБРАТЬ … ИЗ, псевдонимы, параметрыСписок товаров с отбором по группе
2ГДЕ, ПОДОБНО, В, МЕЖДУ, ЕСТЬ NULL, ВЫБОРОтчёт по контрагентам с условиями
3Агрегатные функции, СГРУППИРОВАТЬ ПО, ИМЕЮЩИЕ, ИТОГИСумма поступлений по поставщикам
4Соединения, ОБЪЕДИНИТЬ ВСЕТовары с ценами и остатками в одной выборке
5Временные таблицы, пакетные запросы, менеджер временных таблицЗапрос из трёх шагов
6Виртуальные таблицы регистров: Остатки, Обороты, СрезПоследнихВедомость по складу за период
7–8Оптимизация, разбор запросов типовых конфигурацийПереписанный «медленный» запрос

Лучший учебник после азов — модули типовых конфигураций. Откройте в Конфигураторе модуль любого отчёта или механизма проведения и разберите запросы построчно.

Как устроен запрос 1С: синтаксис и порядок секций

Запрос — это строка текста, которую выполняет объект Запрос. Ключевые слова пишутся по-русски или по-английски, регистр не важен.

Порядок секций строгий:

ВЫБРАТЬ [РАЗРЕШЕННЫЕ] [РАЗЛИЧНЫЕ] [ПЕРВЫЕ N]
    <поля>
[ПОМЕСТИТЬ <временная таблица>]
ИЗ <источники>
[ГДЕ <условие>]
[СГРУППИРОВАТЬ ПО <поля>]
[ИМЕЮЩИЕ <условие на агрегаты>]
[УПОРЯДОЧИТЬ ПО <поля>]
[ИТОГИ ... ПО ...]

Минимальный рабочий пример из кода на встроенном языке:

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

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	Сообщить(Выборка.Наименование);
КонецЦикла;

Что здесь нужно понять с первого дня:

  • 🔹 Источник называется по объекту метаданных: Справочник.Номенклатура, Документ.ПоступлениеТоваров.Товары (табличная часть), РегистрНакопления.<Имя>.
  • 🔹 Параметры начинаются с & и передаются через УстановитьПараметр. Значения в текст запроса не склеивают строками.
  • 🔹 Выполнить().Выбрать() даёт выборку для обхода циклом, Выполнить().Выгрузить() — таблицу значений.
  • 🔹 РАЗРЕШЕННЫЕ нужно, если в базе настроены ограничения доступа на уровне записей: без него запрос у пользователя с ограничениями упадёт с ошибкой, а не отфильтрует строки.
  • 🔹 Через точку можно получать реквизиты ссылок: Товары.Номенклатура.Артикул. Удобно, но каждая точка — это неявное соединение с ещё одной таблицей.

Предопределённые значения и перечисления в тексте запроса задают функцией ЗНАЧЕНИЕ(): ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар), ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка).

Конструктор запросов: учитесь с ним, а не вместо языка

Конструктор вызывается в Конфигураторе из контекстного меню модуля: пункт Конструктор запроса или Конструктор запроса с обработкой результата (второй сразу генерирует код обхода выборки). Если курсор стоит внутри уже написанного текста запроса, конструктор откроет его для правки.

Основные вкладки и что на них отрабатывать:

ВкладкаЧто задаёт
Таблицы и поляИсточники и выбираемые поля, в том числе виртуальные таблицы и их параметры
СвязиСоединения между таблицами и их вид
ГруппировкаПоля группировки и агрегатные функции
УсловияСекция ГДЕ, в том числе произвольные выражения
ДополнительноПЕРВЫЕ, РАЗЛИЧНЫЕ, РАЗРЕШЕННЫЕ, помещение во временную таблицу
Объединения/ПсевдонимыНесколько запросов через ОБЪЕДИНИТЬ и имена колонок
Порядок, ИтогиСортировка и секция ИТОГИ
Пакет запросовПоследовательность запросов в одном тексте

Как тренироваться правильно:

  1. Напишите запрос руками.
  2. Откройте его конструктором и посмотрите, как он разложил ваш текст по вкладкам.
  3. Измените что-то в конструкторе, нажмите «ОК» и сравните, какой текст получился.

Не останавливайтесь на конструкторе. Он хорошо собирает типовые конструкции, но читать и править чужие запросы, разбирать ошибки и оптимизировать их без знания текста не получится. Кроме того, конструктор переформатирует текст и может убрать ваши комментарии.

Отбор данных: условия, параметры, NULL и ВЫБОР

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

ОператорПримерЗаметка
=, <>, <, >Сумма > 1000Сравнение
МЕЖДУ … И …Дата МЕЖДУ &Начало И &КонецГраницы включаются
В (…)Склад В (&СписокСкладов)Параметр может быть массивом или списком значений
В ИЕРАРХИИНоменклатура В ИЕРАРХИИ (&Группа)Учитывает вложенные группы
ПОДОБНОНаименование ПОДОБНО "%кабель%"% — любые символы, _ — один символ
ЕСТЬ NULLЦены.Цена ЕСТЬ NULLЧерез = NULL не проверяют
ССЫЛКАРегистратор ССЫЛКА Документ.ПоступлениеТоваровПроверка типа ссылки

NULL — главный источник сюрпризов у новичков. Он появляется при левом соединении, когда справа нет пары, и при обращении к реквизиту через точку у составного типа. Сравнение с NULL через = не даёт истины, а арифметика с NULL даёт NULL. Поэтому используйте функцию:

ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

Условные значения в полях строят через ВЫБОР:

ВЫБОР
	КОГДА Остатки.КоличествоОстаток > 100 ТОГДА "Много"
	КОГДА Остатки.КоличествоОстаток > 0 ТОГДА "Мало"
	ИНАЧЕ "Нет"
КОНЕЦ КАК Наличие

Дату-константу задают как ДАТАВРЕМЯ(2025, 1, 1), но в рабочем коде даты почти всегда передают параметром. Для приведения составного типа к одному используют ВЫРАЗИТЬ(Поле КАК Справочник.Контрагенты).

Группировка и агрегатные функции в запросах 1С

Агрегатные функции: СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. Число уникальных значений даёт КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле).

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

Пример: сумма поступлений по поставщикам за период, только тех, у кого больше 50 000.

ВЫБРАТЬ
	Поступление.Контрагент КАК Поставщик,
	СУММА(Поступление.СуммаДокумента) КАК Сумма,
	КОЛИЧЕСТВО(Поступление.Ссылка) КАК ЧислоДокументов
ИЗ
	Документ.ПоступлениеТоваров КАК Поступление
ГДЕ
	Поступление.Проведен
	И Поступление.Дата МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
	Поступление.Контрагент
ИМЕЮЩИЕ
	СУММА(Поступление.СуммаДокумента) > 50000
УПОРЯДОЧИТЬ ПО
	Сумма УБЫВ

Разница между ГДЕ и ИМЕЮЩИЕ простая: первое отбирает строки до группировки, второе — группы после неё. Условие на сумму в ГДЕ написать нельзя.

Секция ИТОГИ — особенность 1С, которой нет в SQL. Она добавляет к результату строки промежуточных итогов:

ИТОГИ СУММА(Сумма) ПО Поставщик

Такой результат обходят иерархически: Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам). В отчётах на СКД итоги считает сама система компоновки, поэтому ИТОГИ там обычно не пишут.

Проверьте себя
Где задать условие «сумма по контрагенту больше 10 000»?
Как правильно проверить, что цена не найдена при левом соединении?
Что вернёт КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Товары.Номенклатура)?

Соединения, объединения и временные таблицы

Соединения связывают таблицы по условию в секции ИЗ:

  • ➡️ ВНУТРЕННЕЕ СОЕДИНЕНИЕ — только строки, у которых есть пара с обеих сторон.
  • ⬅️ ЛЕВОЕ СОЕДИНЕНИЕ — все строки левой таблицы, справа NULL, если пары нет. Самый частый вид в отчётах.
  • ↔️ ПОЛНОЕ СОЕДИНЕНИЕ — все строки обеих таблиц.

ОБЪЕДИНИТЬ склеивает результаты нескольких запросов по вертикали. Колонки должны совпадать по количеству и смыслу. ОБЪЕДИНИТЬ ВСЕ оставляет дубли и работает быстрее, просто ОБЪЕДИНИТЬ убирает одинаковые строки.

Временная таблица создаётся словом ПОМЕСТИТЬ и живёт в пределах пакета запросов или менеджера временных таблиц. Запросы пакета разделяют символом ;.

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

Здесь регистр ТоварыНаСкладах взят как учебный пример: в вашей конфигурации имя и измерения будут свои.

Таблицу значений из кода передают в запрос параметром и сразу кладут во временную таблицу:

ВЫБРАТЬ
	Т.Номенклатура КАК Номенклатура,
	Т.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Данные
ИЗ
	&ТаблицаТоваров КАК Т

У колонок таблицы значений должны быть заданы типы через ОписаниеТипов при создании колонок. Без типов запрос не выполнится.

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

Виртуальные таблицы регистров

Эту часть пропускают самоучки, и зря: в реальных задачах большая часть запросов идёт к регистрам, а не к документам.

Виртуальная таблицаРегистрЧто даёт
Остатки(Период, Условие)Накопления (остатков), бухгалтерииОстатки на момент
Обороты(Начало, Конец, …)Накопления, бухгалтерииПриход и расход за период
ОстаткиИОбороты(…)Накопления (остатков), бухгалтерииНачальный остаток, обороты, конечный остаток
СрезПоследних(Период, Условие)Сведений, периодическийПоследнее значение на дату, например цены
СрезПервых(Период, Условие)Сведений, периодическийПервое значение после даты

Главный приём: условия по измерениям пишите в параметрах виртуальной таблицы, а не в ГДЕ.

// Правильно: платформа сразу считает остатки только по нужному складу
РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, Склад = &Склад)

// Медленно: сначала остатки по всем складам, потом отбор
РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки
ГДЕ Остатки.Склад = &Склад

Ещё одна тонкость — граница периода. Если остаток нужен «на момент документа» без учёта его самого, передают не дату, а Новый Граница(МоментВремени, ВидГраницы.Исключая).

Оптимизация запросов 1С: что проверять в первую очередь

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

  1. 🔁 Запрос в цикле. Сто итераций — сто обращений к базе. Соберите данные одним запросом, передав массив параметром в условие В (&Массив).
  2. 🔗 Разыменование составного типа. Движения.Регистратор.Дата, где регистратор может быть ссылкой на 20 видов документов, порождает соединение с каждой из 20 таблиц. Приведите тип через ВЫРАЗИТЬ или возьмите поле Период из самой таблицы.
  3. 📋 Условия виртуальной таблицы в ГДЕ. Перенесите в параметры, как показано выше.
  4. 🧩 Соединение с подзапросом. Оптимизатор СУБД плохо оценивает такие конструкции. Вынесите подзапрос во временную таблицу с ИНДЕКСИРОВАТЬ ПО.
  5. 🔤 ПОДОБНО "%…" по большим таблицам. Шаблон, начинающийся с %, не использует индекс.
  6. 🧮 Лишние поля и РАЗЛИЧНЫЕ «на всякий случай». Берите только то, что используете дальше.

Чем измерять:

  • ⏱️ Замер производительности в Конфигураторе при отладке: показывает, сколько времени заняла каждая строка кода, в том числе Выполнить().
  • 📝 Технологический журнал (logcfg.xml) с событиями DBMSSQL или DBPOSTGRS — фиксирует реальный SQL-текст и длительность запросов к СУБД.
  • 📊 План запроса в СУБД — для серверных баз, когда нужно понять, почему не используется индекс.

Ориентир для самопроверки: откройте свой отчёт на демо-базе и на базе в десять раз больше. Если время выросло непропорционально сильно, ищите причину из списка выше.

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

Нужно ли сначала учить SQL, чтобы освоить язык запросов 1С?
Нет. Можно начать сразу с 1С. Знание SQL ускоряет первые недели, но потом придётся отдельно освоить разыменование ссылок, виртуальные таблицы и ИТОГИ.
Можно ли запросом изменить или удалить данные?
Нет. Язык запросов 1С только читает данные. Запись идёт через объекты встроенного языка или наборы записей регистров.
Чем запрос в коде отличается от запроса в СКД?
Язык один. В СКД к нему добавляются расширения в фигурных скобках для пользовательских отборов и полей, а итоги и группировки строит сама система компоновки.
Как посмотреть результат запроса, не программируя форму?
Через внешнюю обработку «Консоль запросов»: вставьте текст, задайте параметры и выполните. Или в отладчике вычислите Запрос.Выполнить().Выгрузить() и откройте таблицу значений.
Помогает ли сертификат «1С:Специалист» в изучении запросов?
Подготовка к нему заставляет решать задачи на регистры и запросы под ограничение по времени. Это хорошая практика, но не замена работе с реальными базами.