Язык запросов 1С с нуля: что учить, в каком порядке и на чём тренироваться
Содержание
Чтобы изучить язык запросов 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]
<поля>
[ПОМЕСТИТЬ <временная таблица>]
ИЗ <источники>
[ГДЕ <условие>]
[СГРУППИРОВАТЬ ПО <поля>]
[ИМЕЮЩИЕ <условие на агрегаты>]
[УПОРЯДОЧИТЬ ПО <поля>]
[ИТОГИ ... ПО ...]
Минимальный рабочий пример из кода на встроенном языке:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления
| И Номенклатура.Родитель = &Группа
|
|УПОРЯДОЧИТЬ ПО
| Наименование";
Запрос.УстановитьПараметр("Группа", ГруппаТоваров);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование);
КонецЦикла;
Что здесь нужно понять с первого дня:
- 🔹 Источник называется по объекту метаданных:
Справочник.Номенклатура,Документ.ПоступлениеТоваров.Товары(табличная часть),РегистрНакопления.<Имя>. - 🔹 Параметры начинаются с
&и передаются черезУстановитьПараметр. Значения в текст запроса не склеивают строками. - 🔹
Выполнить().Выбрать()даёт выборку для обхода циклом,Выполнить().Выгрузить()— таблицу значений. - 🔹
РАЗРЕШЕННЫЕнужно, если в базе настроены ограничения доступа на уровне записей: без него запрос у пользователя с ограничениями упадёт с ошибкой, а не отфильтрует строки. - 🔹 Через точку можно получать реквизиты ссылок:
Товары.Номенклатура.Артикул. Удобно, но каждая точка — это неявное соединение с ещё одной таблицей.
Предопределённые значения и перечисления в тексте запроса задают функцией ЗНАЧЕНИЕ(): ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар), ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка).
Конструктор запросов: учитесь с ним, а не вместо языка
Конструктор вызывается в Конфигураторе из контекстного меню модуля: пункт Конструктор запроса или Конструктор запроса с обработкой результата (второй сразу генерирует код обхода выборки). Если курсор стоит внутри уже написанного текста запроса, конструктор откроет его для правки.
Основные вкладки и что на них отрабатывать:
| Вкладка | Что задаёт |
|---|---|
| Таблицы и поля | Источники и выбираемые поля, в том числе виртуальные таблицы и их параметры |
| Связи | Соединения между таблицами и их вид |
| Группировка | Поля группировки и агрегатные функции |
| Условия | Секция ГДЕ, в том числе произвольные выражения |
| Дополнительно | ПЕРВЫЕ, РАЗЛИЧНЫЕ, РАЗРЕШЕННЫЕ, помещение во временную таблицу |
| Объединения/Псевдонимы | Несколько запросов через ОБЪЕДИНИТЬ и имена колонок |
| Порядок, Итоги | Сортировка и секция ИТОГИ |
| Пакет запросов | Последовательность запросов в одном тексте |
Как тренироваться правильно:
- Напишите запрос руками.
- Откройте его конструктором и посмотрите, как он разложил ваш текст по вкладкам.
- Измените что-то в конструкторе, нажмите «ОК» и сравните, какой текст получился.
Не останавливайтесь на конструкторе. Он хорошо собирает типовые конструкции, но читать и править чужие запросы, разбирать ошибки и оптимизировать их без знания текста не получится. Кроме того, конструктор переформатирует текст и может убрать ваши комментарии.
Отбор данных: условия, параметры, NULL и ВЫБОР
Секция ГДЕ фильтрует строки до группировки. Набор операторов небольшой, его стоит выучить целиком.
| Оператор | Пример | Заметка |
|---|---|---|
=, <>, <, > | Сумма > 1000 | Сравнение |
МЕЖДУ … И … | Дата МЕЖДУ &Начало И &Конец | Границы включаются |
В (…) | Склад В (&СписокСкладов) | Параметр может быть массивом или списком значений |
В ИЕРАРХИИ | Номенклатура В ИЕРАРХИИ (&Группа) | Учитывает вложенные группы |
ПОДОБНО | Наименование ПОДОБНО "%кабель%" | % — любые символы, _ — один символ |
ЕСТЬ NULL | Цены.Цена ЕСТЬ NULL | Через = NULL не проверяют |
ССЫЛКА | Регистратор ССЫЛКА Документ.ПоступлениеТоваров | Проверка типа ссылки |
NULL — главный источник сюрпризов у новичков. Он появляется при левом соединении, когда справа нет пары, и при обращении к реквизиту через точку у составного типа. Сравнение с NULL через = не даёт истины, а арифметика с NULL даёт NULL. Поэтому используйте функцию:
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
Условные значения в полях строят через ВЫБОР:
ВЫБОР
КОГДА Остатки.КоличествоОстаток > 100 ТОГДА "Много"
КОГДА Остатки.КоличествоОстаток > 0 ТОГДА "Мало"
ИНАЧЕ "Нет"
КОНЕЦ КАК Наличие
Дату-константу задают как ДАТАВРЕМЯ(2025, 1, 1), но в рабочем коде даты почти всегда передают параметром. Для приведения составного типа к одному используют ВЫРАЗИТЬ(Поле КАК Справочник.Контрагенты).
Группировка и агрегатные функции в запросах 1С
Агрегатные функции: СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. Число уникальных значений даёт КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле).
Правило, на котором спотыкается каждый второй учебный запрос: если в запросе есть агрегат, то каждое поле без агрегатной функции должно стоять в СГРУППИРОВАТЬ ПО. Иначе запрос не выполнится.
Пример: сумма поступлений по поставщикам за период, только тех, у кого больше 50 000.
ВЫБРАТЬ
Поступление.Контрагент КАК Поставщик,
СУММА(Поступление.СуммаДокумента) КАК Сумма,
КОЛИЧЕСТВО(Поступление.Ссылка) КАК ЧислоДокументов
ИЗ
Документ.ПоступлениеТоваров КАК Поступление
ГДЕ
Поступление.Проведен
И Поступление.Дата МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
Поступление.Контрагент
ИМЕЮЩИЕ
СУММА(Поступление.СуммаДокумента) > 50000
УПОРЯДОЧИТЬ ПО
Сумма УБЫВ
Разница между ГДЕ и ИМЕЮЩИЕ простая: первое отбирает строки до группировки, второе — группы после неё. Условие на сумму в ГДЕ написать нельзя.
Секция ИТОГИ — особенность 1С, которой нет в SQL. Она добавляет к результату строки промежуточных итогов:
ИТОГИ СУММА(Сумма) ПО Поставщик
Такой результат обходят иерархически: Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам). В отчётах на СКД итоги считает сама система компоновки, поэтому ИТОГИ там обычно не пишут.
Соединения, объединения и временные таблицы
Соединения связывают таблицы по условию в секции ИЗ:
- ➡️
ВНУТРЕННЕЕ СОЕДИНЕНИЕ— только строки, у которых есть пара с обеих сторон. - ⬅️
ЛЕВОЕ СОЕДИНЕНИЕ— все строки левой таблицы, справа NULL, если пары нет. Самый частый вид в отчётах. - ↔️
ПОЛНОЕ СОЕДИНЕНИЕ— все строки обеих таблиц.
ОБЪЕДИНИТЬ склеивает результаты нескольких запросов по вертикали. Колонки должны совпадать по количеству и смыслу. ОБЪЕДИНИТЬ ВСЕ оставляет дубли и работает быстрее, просто ОБЪЕДИНИТЬ убирает одинаковые строки.
Временная таблица создаётся словом ПОМЕСТИТЬ и живёт в пределах пакета запросов или менеджера временных таблиц. Запросы пакета разделяют символом ;.
ВЫБРАТЬ
Товары.Номенклатура КАК Номенклатура,
СУММА(Товары.Количество) КАК Количество
ПОМЕСТИТЬ ВТ_Поступило
ИЗ
Документ.ПоступлениеТоваров.Товары КАК Товары
ГДЕ
Товары.Ссылка.Проведен
И Товары.Ссылка.Дата МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
ИНДЕКСИРОВАТЬ ПО
Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ.Номенклатура КАК Номенклатура,
ВТ.Количество КАК Поступило,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
ВТ_Поступило КАК ВТ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
&Конец,
Номенклатура В
(ВЫБРАТЬ ВТ_Поступило.Номенклатура ИЗ ВТ_Поступило)) КАК Остатки
ПО ВТ.Номенклатура = Остатки.Номенклатура
Здесь регистр ТоварыНаСкладах взят как учебный пример: в вашей конфигурации имя и измерения будут свои.
Таблицу значений из кода передают в запрос параметром и сразу кладут во временную таблицу:
ВЫБРАТЬ
Т.Номенклатура КАК Номенклатура,
Т.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Данные
ИЗ
&ТаблицаТоваров КАК Т
У колонок таблицы значений должны быть заданы типы через ОписаниеТипов при создании колонок. Без типов запрос не выполнится.
Чтобы временная таблица пережила один запрос и использовалась в следующем, создают Новый МенеджерВременныхТаблиц и присваивают его свойству МенеджерВременныхТаблиц у каждого запроса. Пакет из нескольких результатов получают методом ВыполнитьПакет(): он возвращает массив результатов по порядку запросов.
Виртуальные таблицы регистров
Эту часть пропускают самоучки, и зря: в реальных задачах большая часть запросов идёт к регистрам, а не к документам.
| Виртуальная таблица | Регистр | Что даёт |
|---|---|---|
Остатки(Период, Условие) | Накопления (остатков), бухгалтерии | Остатки на момент |
Обороты(Начало, Конец, …) | Накопления, бухгалтерии | Приход и расход за период |
ОстаткиИОбороты(…) | Накопления (остатков), бухгалтерии | Начальный остаток, обороты, конечный остаток |
СрезПоследних(Период, Условие) | Сведений, периодический | Последнее значение на дату, например цены |
СрезПервых(Период, Условие) | Сведений, периодический | Первое значение после даты |
Главный приём: условия по измерениям пишите в параметрах виртуальной таблицы, а не в ГДЕ.
// Правильно: платформа сразу считает остатки только по нужному складу
РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, Склад = &Склад)
// Медленно: сначала остатки по всем складам, потом отбор
РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки
ГДЕ Остатки.Склад = &Склад
Ещё одна тонкость — граница периода. Если остаток нужен «на момент документа» без учёта его самого, передают не дату, а Новый Граница(МоментВремени, ВидГраницы.Исключая).
Оптимизация запросов 1С: что проверять в первую очередь
Медленный запрос почти всегда медленный по одной из немногих причин. Проверяйте по порядку:
- 🔁 Запрос в цикле. Сто итераций — сто обращений к базе. Соберите данные одним запросом, передав массив параметром в условие
В (&Массив). - 🔗 Разыменование составного типа.
Движения.Регистратор.Дата, где регистратор может быть ссылкой на 20 видов документов, порождает соединение с каждой из 20 таблиц. Приведите тип черезВЫРАЗИТЬили возьмите полеПериодиз самой таблицы. - 📋 Условия виртуальной таблицы в
ГДЕ. Перенесите в параметры, как показано выше. - 🧩 Соединение с подзапросом. Оптимизатор СУБД плохо оценивает такие конструкции. Вынесите подзапрос во временную таблицу с
ИНДЕКСИРОВАТЬ ПО. - 🔤
ПОДОБНО "%…"по большим таблицам. Шаблон, начинающийся с%, не использует индекс. - 🧮 Лишние поля и
РАЗЛИЧНЫЕ«на всякий случай». Берите только то, что используете дальше.
Чем измерять:
- ⏱️ Замер производительности в Конфигураторе при отладке: показывает, сколько времени заняла каждая строка кода, в том числе
Выполнить(). - 📝 Технологический журнал (
logcfg.xml) с событиямиDBMSSQLилиDBPOSTGRS— фиксирует реальный SQL-текст и длительность запросов к СУБД. - 📊 План запроса в СУБД — для серверных баз, когда нужно понять, почему не используется индекс.
Ориентир для самопроверки: откройте свой отчёт на демо-базе и на базе в десять раз больше. Если время выросло непропорционально сильно, ищите причину из списка выше.
Частые вопросы
Нужно ли сначала учить SQL, чтобы освоить язык запросов 1С?
ИТОГИ.Можно ли запросом изменить или удалить данные?
Чем запрос в коде отличается от запроса в СКД?
Как посмотреть результат запроса, не программируя форму?
Запрос.Выполнить().Выгрузить() и откройте таблицу значений.