Конструктор запросов 1С — визуальный редактор Конфигуратора: вы перетаскиваете таблицы и поля, задаёте связи, условия и группировки, а он генерирует текст запроса и вставляет его в модуль. Ниже — где его открыть, все закладки на одном сквозном примере, код на выходе, горячие клавиши и случаи, когда быстрее писать руками.
Работа с конструктором запросов 1С 8.3 одинакова в любой конфигурации; имена объектов в примерах — из УТ 11.4 (в КА 2.5 такие же), подписи — по платформе 8.3.27.
Где находится конструктор запросов в 1С, зависит от того, где лежит текст запроса:
"ВЫБРАТЬ …"), затем контекстное меню → «Конструктор запроса...» или главное меню «Текст» → «Конструктор запроса...». По «ОК» новый текст заменит старый.Задача: по каждому товару за период показать, сколько продано за вычетом возвратов, на какую сумму и сколько осталось на складах. Это пакет из двух запросов: первый объединяет строки реализаций и возвратов во временную таблицу, второй группирует их и присоединяет остатки. Документы взяты ради объединения — в учётных отчётах УТ продажи обычно берут из регистра ВыручкаИСебестоимостьПродаж. Собираем закладку за закладкой; переходить можно и кнопками «Далее >» и «< Назад».
В дереве «База данных» раскройте документ РеализацияТоваровУслуг и перетащите табличную часть Товары в «Таблицы», а из неё в «Поля» — Номенклатура, Количество, СуммаСНДС. Здесь же команды «Создать вложенный запрос», «Параметры виртуальной таблицы...», «Заменить таблицу...» и «Переименовать таблицу...». Выражение вместо поля добавляют через контекстное меню списка «Поля» → «Добавить»: откроется окно «Произвольное выражение» с функциями языка запросов.
Условия в конструкторе запросов 1С задаются перетаскиванием поля в список условий: для поля выбирают вид сравнения и имя параметра, а параметр с & конструктор заведёт сам. Для МЕЖДУ и выражений удобнее флажок «Произвольное» — условие пишется текстом. Нам нужны: …Ссылка.Проведен и …Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода. Значения параметров задаются в коде, подробнее — в статье про параметры запроса.
В группе «Тип запроса» выберите «Создание временной таблицы», в поле «Имя временной таблицы:» впишите ВТ_Продажи. В тексте появится ПОМЕСТИТЬ, в окне — закладка «Индекс» для индексов временной таблицы. Здесь же флажки «Первые», «Без повторяющихся» (РАЗЛИЧНЫЕ), «Разрешенные» и «Блокировать получаемые данные для последующего изменения».
Добавьте в список запросов объединения второй запрос — для возвратов — и настройте его так же, как первый, но с таблицей Документ.ВозвратТоваровОтКлиента.Товары. У полей Количество и СуммаСНДС через «Изменить» поставьте минус: при суммировании возвраты вычтутся. В таблице псевдонимов строка — поле результата, колонка — часть объединения; имя поля и соответствие меняются клавишей Enter. Назовите третье поле Сумма. Флажок «Без дубл.» не ставьте: он превращает ОБЪЕДИНИТЬ ВСЕ в ОБЪЕДИНИТЬ, и одинаковые строки разных документов схлопнутся в одну.
Добавьте в пакет второй запрос; между запросами пакета переключают закладки у правого края окна. В дереве «База данных» появится ветка временных таблиц с ВТ_Продажи. Перенесите её и РегистрНакопления.ТоварыНаСкладах.Остатки, выделите остатки и через «Параметры виртуальной таблицы...» ограничьте их товарами из продаж. Как работают ПОМЕСТИТЬ и УНИЧТОЖИТЬ, разобрано в статье о временных таблицах.
Закладка появляется, когда таблиц больше одной. Строка связи: «Таблица 1» — ВТ_Продажи с флажком «Все», «Таблица 2» — остатки без флажка, «Условие связи» — равенство полей Номенклатура. Флажок «Все» у первой таблицы даёт ЛЕВОЕ СОЕДИНЕНИЕ, у второй — ПРАВОЕ, у обеих — ПОЛНОЕ, без флажков — ВНУТРЕННЕЕ. Сложное условие пишут с флажком «Произвольное». Подробнее — в статье про соединения в запросе.
В «Поле группировки» перетащите ВТ_Продажи.Номенклатура, в «Суммируемое поле» — Количество и Сумма с функцией «Сумма» и остаток, обёрнутый в ЕСТЬNULL(…, 0), с функцией «Максимум». На «Объединения/Псевдонимы» второго запроса назовите поля Продано, Выручка, Остаток, на «Порядке» добавьте Выручка по убыванию. «Итоги» добавили бы ИТОГИ … ПО — здесь они не нужны.
«ОК» вставит текст в модуль, а посмотреть его заранее можно кнопкой «Запрос». Функция с результатом:
// Продажи за период по номенклатуре (реализации минус возвраты)
// и текущий остаток на складах. Текст собран конструктором запросов:
// пакет из двух запросов, первый — объединение во временную таблицу.
Функция ПродажиИОстатки(НачалоПериода, КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
| РеализацияТоваровУслугТовары.Количество КАК Количество,
| РеализацияТоваровУслугТовары.СуммаСНДС КАК Сумма
|ПОМЕСТИТЬ ВТ_Продажи
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
|ГДЕ
| РеализацияТоваровУслугТовары.Ссылка.Проведен
| И РеализацияТоваровУслугТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ВозвратТоваровОтКлиентаТовары.Номенклатура,
| -ВозвратТоваровОтКлиентаТовары.Количество,
| -ВозвратТоваровОтКлиентаТовары.СуммаСНДС
|ИЗ
| Документ.ВозвратТоваровОтКлиента.Товары КАК ВозвратТоваровОтКлиентаТовары
|ГДЕ
| ВозвратТоваровОтКлиентаТовары.Ссылка.Проведен
| И ВозвратТоваровОтКлиентаТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Продажи.Номенклатура КАК Номенклатура,
| СУММА(ВТ_Продажи.Количество) КАК Продано,
| СУММА(ВТ_Продажи.Сумма) КАК Выручка,
| МАКСИМУМ(ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0)) КАК Остаток
|ИЗ
| ВТ_Продажи КАК ВТ_Продажи
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
| ,
| Номенклатура В
| (ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура
| ИЗ
| ВТ_Продажи КАК Продажи)) КАК ТоварыНаСкладахОстатки
| ПО ВТ_Продажи.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
|
|СГРУППИРОВАТЬ ПО
| ВТ_Продажи.Номенклатура
|
|УПОРЯДОЧИТЬ ПО
| Выручка УБЫВ";
// Параметры, которые конструктор завёл на закладке «Условия»
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
ПОМЕСТИТЬ стоит в первой части объединения, но в ВТ_Продажи попадает весь результат ОБЪЕДИНИТЬ ВСЕ.Остатки(, Номенклатура В (…)) отбирает товары до расчёта остатков — это быстрее, чем то же условие в ГДЕ.Номенклатура, поэтому остатки приходят одной строкой на товар (сумма по складам) и продажи не размножаются.ЕСТЬNULL заменит NULL нулём. МАКСИМУМ нужен, потому что поле не в группировке, а в строках товара значение одно.КонецДня() — дата документа хранится со временем, без этого выпадет последний день периода.Если итог не сходится, посмотрите, сколько строк дал каждый запрос пакета. ВыполнитьПакет() для запроса с ПОМЕСТИТЬ возвращает одну строку с числом записей, а ВыполнитьПакетСПромежуточнымиДанными() (8.3.8+) — содержимое временной таблицы:
// Отладка пакета: сколько строк вернул каждый запрос.
// Для запроса с ПОМЕСТИТЬ ВыполнитьПакетСПромежуточнымиДанными (8.3.8+)
// возвращает содержимое временной таблицы, а не одну строку с количеством.
Функция СтрокПоЗапросамПакета(ТекстЗапроса, ПараметрыЗапроса) Экспорт
Запрос = Новый Запрос(ТекстЗапроса);
Для Каждого Параметр Из ПараметрыЗапроса Цикл
Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
Результаты = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
Строки = Новый Массив;
Для Индекс = 0 По Результаты.ВГраница() Цикл
Результат = Результаты[Индекс];
Если Результат = Неопределено Тогда
Описание = "уничтожение временной таблицы";
Иначе
Описание = Формат(Результат.Выбрать().Количество(), "ЧН=0") + " стр.";
КонецЕсли;
Строки.Добавить(СтрШаблон("Запрос %1: %2", Индекс + 1, Описание));
КонецЦикла;
Возврат СтрСоединить(Строки, Символы.ПС);
КонецФункции
Параметры передаются структурой: Новый Структура("НачалоПериода, КонецПериода", Дата1, Дата2).
Этот вариант добавляет закладку «Обработка результата»: «Обход результата», «Вывод в табличный документ» или «Вывод в диаграмму». Для обхода вставляется код выполнения и цикл по выборке между служебными комментариями, для табличного документа конструктор ещё и создаёт макет в объекте метаданных. Вызывайте его внутри серверной процедуры:
// Так выглядит вставка «Конструктора запроса с обработкой результата»
// (тип обработки «Обход результата») внутри серверной процедуры.
Процедура ВывестиТоварыВида(ВидНоменклатуры) Экспорт
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ВидНоменклатуры = &ВидНоменклатуры
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("ВидНоменклатуры", ВидНоменклатуры);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Вставить обработку выборки ВыборкаДетальныеЗаписи
// Строку ниже дописали руками: повторный вызов конструктора её сотрёт
Сообщить(СтрШаблон("%1, артикул %2", ВыборкаДетальныеЗаписи.Ссылка, ВыборкаДетальныеЗаписи.Артикул));
КонецЦикла;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецПроцедуры
Всё между маркерами конструктор перезапишет при следующем вызове. Дописываете логику — удалите маркеры и правьте запрос обычным конструктором.
В режиме 1С:Предприятие конструктор — это объект КонструкторЗапроса, доступный и в тонком, и в веб-клиенте. Немодально его открывает Показать() (8.3.5+), в 8.3.18+ есть ОткрытьАсинх(); ОткрытьМодально() работает только в толстом клиенте. Кнопка «Конструктор» для своей обработки:
// Модуль формы своей консоли или обработки: команда «Конструктор».
// Объект.ТекстЗапроса — строковый реквизит обработки с текстом запроса.
&НаКлиенте
Процедура ОткрытьКонструкторЗапроса(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияКонструктора", ЭтотОбъект);
Попытка
// Конструктор разбирает текст: с синтаксической ошибкой он не откроется
Конструктор = Новый КонструкторЗапроса(Объект.ТекстЗапроса);
Конструктор.Показать(Оповещение); // немодально, с 8.3.5
Исключение
ПоказатьПредупреждение(, "Конструктор не разобрал текст запроса:" + Символы.ПС
+ КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияКонструктора(Текст, ДополнительныеПараметры) Экспорт
// Неопределено — окно закрыли без «ОК», текст не трогаем
Если Текст = Неопределено Тогда
Возврат;
КонецЕсли;
Объект.ТекстЗапроса = Текст;
Модифицированность = Истина;
КонецПроцедуры
Если до вызова Показать() установить РежимКомпоновкиДанных = Истина, конструктор откроется в режиме СКД.
Что пригодится при работе с конструктором:
| Действие | Клавиши |
|---|---|
| Открыть конструктор запроса | в официальном списке сочетаний его нет: контекстное меню или «Текст» → «Конструктор запроса...» |
| Справка по конструктору | F1 в его окне |
| Переименовать поле на «Объединения/Псевдонимы» | Enter |
| Найти / заменить в тексте пакета | Ctrl+F / Ctrl+H |
| Форматировать вставленный блок | Shift+Alt+F |
| Закомментировать / раскомментировать | Ctrl+Num/ / Ctrl+Shift+Num/ |
| Проверка модуля | Ctrl+F7 — текст запроса внутри строки она не проверяет |
Писать запросы через конструктор выгодно там, где руками легко ошибиться: соединения, виртуальные таблицы, объединения, пакеты. Руками быстрее:
+ и подстановки СтрЗаменить конструктор целиком не откроет.Дописать условие в готовый текст из кода можно через СхемаЗапроса — программный аналог конструктора (сервер, толстый клиент, внешнее соединение):
// Дописывает условие в ГДЕ каждой части объединения запроса пакета —
// то же, что закладка «Условия», только из кода. В шаблоне условия
// #Т заменяется псевдонимом первой таблицы каждой части.
Функция ДобавитьУсловиеВЗапросПакета(ТекстЗапроса, НомерЗапроса, ШаблонУсловия) Экспорт
Схема = Новый СхемаЗапроса;
Схема.УстановитьТекстЗапроса(ТекстЗапроса);
ЗапросПакета = Схема.ПакетЗапросов[НомерЗапроса - 1];
Если ТипЗнч(ЗапросПакета) <> Тип("ЗапросВыбораСхемыЗапроса") Тогда
ВызватьИсключение СтрШаблон("Запрос %1 пакета — не запрос ВЫБРАТЬ", НомерЗапроса);
КонецЕсли;
Для Каждого Оператор Из ЗапросПакета.Операторы Цикл
Псевдоним = Оператор.Источники[0].Источник.Псевдоним;
Оператор.Отбор.Добавить(СтрЗаменить(ШаблонУсловия, "#Т", Псевдоним));
КонецЦикла;
// Текст пересобирается целиком — в том же виде, что выдаёт конструктор
Возврат Схема.ПолучитьТекстЗапроса();
КонецФункции
Вызов ДобавитьУсловиеВЗапросПакета(ТекстЗапроса, 1, "#Т.Номенклатура.ВидНоменклатуры В (&ВидыНоменклатуры)") добавит отбор в обе части объединения из примера.
+. Ошибку ищут руками, склейку собирают в один литерал или меняют через СхемаЗапроса.Запрос.НайтиПараметры().&НаКлиенте модуля формы. Код с Новый Запрос должен стоять в серверной процедуре.ГДЕ оно отсекает NULL, и соединение становится внутренним — переносите его в параметры виртуальной таблицы или в условие связи.Да, через объект КонструкторЗапроса — так работают консоли запросов (листинг выше). По справке платформы, в поле текстового документа с расширением «Язык запросов» конструктор доступен пользователям с административными правами.
Конструктор разбирает текст в свою модель и по «ОК» генерирует его заново: свои отступы, полные имена полей, КАК у каждого поля. Псевдонимы из вашего текста он сохраняет — на «Объединения/Псевдонимы» они выделены жирным, а комментарии теряются.
В модуле расширения видны только объекты расширения и заимствованные — остальные включает кнопка «Отображать таблицы и поля расширяемой конфигурации». Таблицы изменений показывает кнопка «Отображать таблицы изменений», а длинный список сортирует «Упорядочить список».
Если запрос — часть отчёта или обработки, которая считает неверно или работает минутами, задачу проще отдать программисту. На 1c-only.ru этим занимается направление доработки отчётов и обработок 1С: опишите задачу через «Разместить задачу» — оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.