Запрос без ручного кода: от выбора таблицы до отчёта по остаткам и оборотам
Содержание
Конструктор запросов в 1С открывается из Конфигуратора: в модуле щёлкните правой кнопкой и выберите Конструктор запроса (или Конструктор запроса с обработкой результата, если нужен ещё и код обхода выборки). В схеме компоновки данных он вызывается кнопкой у набора данных, а пользователю без Конфигуратора доступен через внешнюю обработку
«Консоль запросов».
Дальше всё делается мышью: выбираете таблицы, перетаскиваете поля, задаёте связи и условия — конструктор сам пишет текст на языке запросов. Для аналитики и отчётов этого хватает в девяти случаях из десяти. Оставшийся десятый — тонкая оптимизация — тоже начинается с конструктора, просто потом текст правят руками.
Где открыть конструктор запросов и как устроено его окно
Конструктор один и тот же, меняется только точка входа.
| Где работаете | Как вызвать | Что получите |
|---|---|---|
| Модуль в Конфигураторе | ПКМ в тексте модуля → Конструктор запроса | Текст запроса в строковой переменной |
| Модуль в Конфигураторе | ПКМ → Конструктор запроса с обработкой результата | Текст + код Новый Запрос, Выполнить(), цикл по выборке |
| Схема компоновки (СКД) | Набор данных «Запрос» → кнопка Конструктор запроса... | Текст запроса и вкладка настроек компоновки |
| Пользовательский режим | Внешняя обработка «Консоль запросов» | Запрос, который можно сразу выполнить и посмотреть результат |
💡 Чтобы отредактировать уже написанный запрос, поставьте курсор внутрь его текста (в строку, которая начинается с "ВЫБРАТЬ или с |) и снова вызовите конструктор. Он разберёт текст и откроет его на вкладках.
Комментарии внутри текста запроса конструктор не сохраняет, а форматирование перестраивает по-своему. Если в запросе были пояснения //, вынесите их над переменной до открытия конструктора.
Вкладки окна
- 📋 Таблицы и поля — дерево метаданных слева, выбранные таблицы в центре, поля справа.
- 🔗 Связи — как соединяются таблицы.
- 📊 Группировка — по каким полям сворачивать строки и что суммировать.
- 🔍 Условия — отборы, они же блок
ГДЕ. - ⚙️ Дополнительно —
ПЕРВЫЕ N,РАЗЛИЧНЫЕ,РАЗРЕШЕННЫЕ, тип запроса (выборка или временная таблица). - 🔀 Объединения/Псевдонимы — несколько запросов в один результат и имена колонок.
- ↕️ Порядок — сортировка.
- 📦 Пакет запросов — несколько запросов подряд, обычно с временными таблицами.
Часть вкладок появляется только при нужных условиях. Например, «Индекс» видна, когда запрос создаёт временную таблицу, а «Компоновка данных» — когда конструктор вызван из СКД.
Первый запрос в конструкторе: поля, отборы, сортировка, группировка
Разберём простую задачу: список контрагентов-покупателей, отсортированный по наименованию.
- На вкладке «Таблицы и поля» раскройте ветку
Справочникии перетащите нужный справочник в колонку «Таблицы». - Двойным щелчком перенесите поля
Ссылка,Наименование,ИННв колонку «Поля». - На вкладке «Условия» перетащите поле, по которому отбираете. Конструктор создаст условие вида
Поле = &Полеи параметр с тем же именем. - Если нужно выражение сложнее простого равенства, отметьте флажок «Произвольное» и впишите условие руками:
Таблица.Наименование ПОДОБНО &Шаблон. - На вкладке «Порядок» добавьте
Наименованиеи выберите направление «Возрастание». - Нажмите «ОК» — текст окажется в модуле.
Группировка и итоговые суммы
Группировка нужна, когда из тысяч строк надо получить свод. На вкладке «Группировка» в левую колонку переносят поля, по которым сворачивать (контрагент, номенклатура), в правую — числовые поля с агрегатной функцией.
| Функция | Что считает | Пример задачи |
|---|---|---|
СУММА | Сумму значений | Выручка по клиенту |
КОЛИЧЕСТВО | Число строк | Сколько было документов |
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) | Число уникальных значений | Сколько разных товаров купил клиент |
МАКСИМУМ / МИНИМУМ | Крайние значения | Дата последней покупки |
СРЕДНЕЕ | Среднее арифметическое | Средний чек |
⚠️ Поле, которое стоит в колонке «Поля», но не попало ни в группировку, ни в агрегат, вызовет ошибку при выполнении. Конструктор обычно сам раскладывает поля, но после ручных правок текста это частая причина сбоя.
Связи между таблицами в конструкторе запросов
Как только в колонке «Таблицы» две таблицы и больше, нужна вкладка «Связи». В каждой строке: левая таблица, флажок «Все», правая таблица, флажок «Все» и условие связи.
Тип соединения задают флажки «Все»:
| Флажки «Все» | Соединение | Что вернёт |
|---|---|---|
| Ни один | ВНУТРЕННЕЕ СОЕДИНЕНИЕ | Только строки, у которых есть пара в обеих таблицах |
| Только у левой | ЛЕВОЕ СОЕДИНЕНИЕ | Все строки левой, справа — найденное или NULL |
| Только у правой | ПРАВОЕ СОЕДИНЕНИЕ | Зеркально левому |
| У обеих | ПОЛНОЕ СОЕДИНЕНИЕ | Все строки обеих таблиц |
Для отчётов чаще всего нужно левое соединение. Пример: справочник номенклатуры слева, остатки справа. Внутреннее соединение выкинет товары без остатка, и пользователь решит, что их нет в базе.
💡 При левом соединении пустые значения справа приходят как NULL. Чтобы в отчёте был ноль, а не пустая ячейка, оберните поле в ЕСТЬNULL(Остатки.КоличествоОстаток, 0). В конструкторе это делается через редактирование выражения поля на вкладке «Таблицы и поля».
Откуда берутся задвоенные суммы
Если связать документ с табличной частью другого документа по контрагенту, каждая строка слева размножится на число совпадений справа. Сумма документа в отчёте вырастет в разы. Правило простое: прежде чем суммировать после соединения, проверьте, что связь идёт «один к одному» или «многие к одному». Если нет — сначала сгруппируйте правую таблицу во временной таблице, а потом соединяйте.
Виртуальные таблицы регистров: остатки, обороты, срез последних
Для аналитики главное в конструкторе запросов — виртуальные таблицы. Они есть у регистров и считают итоги на стороне платформы, а не перебором движений.
| Виртуальная таблица | Регистр | Когда брать |
|---|---|---|
Остатки | Регистр накопления (вид «Остатки»), бухгалтерский | Сколько чего есть на дату |
Обороты | Регистр накопления, бухгалтерский | Приход, расход, продажи за период |
ОстаткиИОбороты | Регистр накопления (вид «Остатки»), бухгалтерский | Ведомость: начальный остаток, приход, расход, конечный остаток |
СрезПоследних | Периодический регистр сведений | Актуальные цены, курсы, ставки на дату |
СрезПервых | Периодический регистр сведений | Первое значение после даты |
Как задать параметры виртуальной таблицы
- Перетащите в «Таблицы» не сам регистр, а его вложенную строку, например
РегистрНакопления.<Имя>.Остатки. - Выделите таблицу и нажмите кнопку
Параметры виртуальной таблицынад списком таблиц. - В поле «Период» укажите
&Дата, в «Условие» — отбор по измерениям:Склад = &Склад. - Для
ОборотыиОстаткиИОборотыукажите начало и конец периода, а также «Периодичность» (День, Месяц, Регистратор и т. д.), если нужна разбивка по датам.
Отбор по измерениям ставьте в параметры виртуальной таблицы, а не на вкладку «Условия». Условие в параметрах платформа применяет до расчёта итогов. Условие в ГДЕ срабатывает после: сначала посчитаются остатки по всем складам, потом лишнее отбросится.
Ловушка с датой остатков
Остатки(&Дата) возвращает остаток на начало этого момента. Если передать дату 31.03 без времени, движения 31 марта в остаток не войдут. Для остатка на конец дня передавайте КонецДня(Дата) или границу с включением:
Запрос.УстановитьПараметр("Дата", Новый Граница(КонецДня(ДатаОтчета), ВидГраницы.Включая));
Параметры запроса: как сделать отчёт гибким
Параметр — это имя с амперсандом в тексте: &Склад, &НачалоПериода. Текст запроса остаётся неизменным, меняется только значение. Так один запрос обслуживает любой склад и любой период.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, Склад = &Склад) КАК Остатки";
Запрос.УстановитьПараметр("Дата", КонецДня(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Склад", Склад);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Строка(Выборка.Номенклатура) + ": " + Формат(Выборка.Количество, "ЧГ=0"));
КонецЦикла;
Имя регистра ТоварыНаСкладах здесь условное: подставьте то, что видите в дереве метаданных своей конфигурации.
Приёмы с параметрами
- 📌 Список значений. Условие
Склад В (&Склады)принимает массив или список значений — отбор сразу по нескольким складам. - 📌 Необязательный отбор.
(&Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) ИЛИ Остатки.Склад = &Склад)— если склад не выбран, отбор не работает . Удобно, но на больших таблицах медленно; лучше собирать условие в коде. - 📌 Параметры в СКД. Конструктор, вызванный из схемы компоновки, сам добавляет параметры на вкладку «Параметры» схемы. Пользователь видит их в настройках отчёта и меняет без программиста.
- 📌 Предопределённые значения. Вместо параметра для констант используйте
ЗНАЧЕНИЕ(Перечисление.<Имя>.<Значение>)— конструктор вставит его через редактор выражений.
Почему запрос тормозит и как ускорить его в конструкторе
Медленный запрос почти всегда выдаёт одна из пяти причин. Каждую можно найти и исправить, не выходя из конструктора.
- Отбор в
ГДЕвместо параметров виртуальной таблицы. Перенесите условие по измерениям вПараметры виртуальной таблицы— см. раздел выше. - Обращение через точку к составному полю.
Регистратор.ДатаилиРегистратор.Контрагентзаставляют платформу соединиться со всеми таблицами документов, которые могут быть регистратором. Приведите тип:ВЫРАЗИТЬ(Регистратор КАК Документ.<Имя>).Контрагент. - Соединение с подзапросом. Подзапрос в соединении оптимизатор СУБД оценивает плохо. Вынесите его в отдельный запрос пакета с типом «Создание временной таблицы» и проиндексируйте по полю связи на вкладке «Индекс».
ИЛИв условиях по разным полям. Индекс в таком случае часто не используется. Разбейте запрос на два и сложите результаты черезОБЪЕДИНИТЬ ВСЕна вкладке «Объединения/Псевдонимы».- Лишние поля и строки. Каждое поле — это данные, которые надо прочитать и передать клиенту. Убирайте неиспользуемое, а для проверок «есть ли хоть одна запись» ставьте
ПЕРВЫЕ 1на вкладке «Дополнительно».
Как измерить, что стало быстрее
В пользовательском режиме консоль запросов показывает время выполнения. В Конфигураторе запустите отладку и включите замер производительности из меню Отладка — он покажет, сколько времени ушло на строку Запрос.Выполнить(). Сравнивайте на одних и тех же параметрах: первый запуск после перезапуска сервера всегда медленнее из-за кэша СУБД.
💡 Временная таблица без индекса на маленьких объёмах может работать даже быстрее: индекс тоже надо построить. Индексируйте, когда в таблице тысячи строк и по ней идёт соединение.
Готовые примеры запросов для отчётов и выгрузок
Ниже — три типовых шаблона. Соберите их в конструкторе, а потом сверьтесь с текстом.
Ведомость по остаткам и оборотам за месяц
В конструкторе: таблица ОстаткиИОбороты, параметры периода &НачалоПериода и &КонецПериода, периодичность «Месяц».
ВЫБРАТЬ
ОИО.Номенклатура КАК Номенклатура,
ОИО.КоличествоНачальныйОстаток КАК НачОстаток,
ОИО.КоличествоПриход КАК Приход,
ОИО.КоличествоРасход КАК Расход,
ОИО.КоличествоКонечныйОстаток КАК КонОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Месяц, , Склад = &Склад) КАК ОИО
УПОРЯДОЧИТЬ ПО
Номенклатура
Проверка арифметики: если на начало 120 штук, приход 80, расход 150, конечный остаток должен быть 50. Если цифры не сходятся, скорее всего, отбор задан в ГДЕ и отсёк часть движений.
Товары с актуальной ценой (пакет запросов)
Первый запрос пакета — СрезПоследних регистра цен на дату, тип «Создание временной таблицы», имя ВТ_Цены, индекс по номенклатуре. Второй — справочник номенклатуры с левым соединением к ВТ_Цены. Товары без цены останутся в списке с нулём благодаря ЕСТЬNULL.
Выгрузка для внешней системы
Для интеграции результат удобно выгрузить в таблицу значений и уже из неё формировать файл или ответ HTTP-сервиса:
Таблица = Запрос.Выполнить().Выгрузить();
Для Каждого Строка Из Таблица Цикл
// формирование строки файла или элемента JSON
КонецЦикла;
Используйте ВЫБРАТЬ РАЗРЕШЕННЫЕ (флажок на вкладке «Дополнительно»), если выгрузку запускает пользователь с ограничением прав на уровне записей. Без него запрос упадёт с ошибкой доступа там, где можно было просто не показать чужие данные.
Ошибки при работе с конструктором запросов и как их распознать
&Параметр, а в коде нет УстановитьПараметр с тем же именем. Сверьте написание: имена параметров не чувствительны к регистру, но опечатка в одной букве даёт новый параметр.Остатки передан датой без времени, поэтому движения последнего дня не учтены. Передайте КонецДня или Новый Граница(..., ВидГраницы.Включая).NULL. Оберните его в ЕСТЬNULL(Поле, 0).Частые вопросы
Можно ли пользоваться конструктором запросов без Конфигуратора?
Файл → Открыть. Нужно право на открытие внешних обработок.Чем «Конструктор запроса» отличается от варианта «с обработкой результата»?
Запрос, установку параметров, выполнение и цикл обхода выборки или выгрузку в таблицу значений.