В 8.3.5 у нас появилась восможность программной работы с текстом запроса.
Новость об этом можно прочитать на сайте 1С "Управляемый конструктор запроса и объектная модель схемы запроса" .
Для анализа конкретного запроса рекоммендую "Дерево объектной модели схемы запроса".
Попробуем разобраться, что такое вообще запрос. В каком формате он представлен в 1С и на сервере ИБ.
Упрощенно можно выделить следующие уровни работы с запросом:
1. Запрос на языке СУБД. На этом уровне запрос представляет собой текстовую строку в синтаксисе конкретной СУБД.
Например "SELECT field1 FROM table1 WHERE table1.field2 > 100".
2. Драйвер конкретной СУБД. Это утилита, которая служит связующим звеном между программой и сервером. Она получает запрос от программы и передает его к СУБД.
На этом уровне 1С работает с внешними источниками данных.
3. Универсальный программный интерфейс. Это универсальный компонент, позволяющий программе получить доступ к данным в различных ИБ. Его также можно назвать менеджером драйверов. К нему в виде DSN подключаются используемые на компьютере драйвера конкретных СУБД. В зависимости от используемой системы тут может быть компонент ODBC, OLE DB, JDBC, ADO.NET либо любого другого стандарта. Судя по http://its.1c.ru/db/metod8dev#content:2926:1 на текущий момент 1С использует OLE DB. В платформе 7.7 использовался ODBC.
4. Объект на сервере 1С. На этом уровне выполняется работа сервера приложений с запросом.
Насколько я понимаю, в платформе на языке Си описан объект запроса для которого прописаны методы формирования текста SQL. С этим объектом запроса работают платформенные объекты (конструктор запросов, построитель и т.д.)
5. Запрос на языке 1С. На этом уровне запрос представляет из себя текст, написанный на псевдо-SQL-языке вида "ВЫБРАТЬ Справочник.ИмяСправочника.ИмяПоля ИЗ Справочник.ИмяСправочника"
Насколько я понимаю, с введением объекта "Схема запроса" ничего нового в платформе не изобрели.
Ранее мы могли работать только с текстовым представлением запроса (уровень 5). Это наиболее простой и понятный способ, хотя и не всегда удобный.
Сейчас нам дали доступ к объекту (уровень 4), с которыми ранее работали только платформенные механизмы.
Если проанализировать объект "Схема запросов", то его свойства очень четко пересекаются с конструктором запросов.
Каждому элементу и свойству можно найти визуальный аналог в конструкторе запросов.
Каждому клику в конструкторе можно подобрать аналогичную команду.
Например:
Закладка "Пакет запросов" = СхемаЗапроса.ПакетЗапросов;
Закладка "Таблицы и поля" = СхемаЗапроса.ПакетЗапросов[0].ДоступныеТаблицы;
Клик на таблице "Справочники" - "Номенклатура" = СхемаЗапроса.ПакетЗапросов[0].Операторы[0].Источники.Добавить("Справочник.Номенклатура");
Таким образом мы можем программно сформировать практически любой запрос, который можем сделать конструктором.
Разумеется, программное создание намного сложнее и длительнее, чем просто работа с конструктором или даже написание текста запроса вручную.
Для статических запросов, текст которых не изменяется, нет никакого смысла использовать схему.
Программная работа требует более глубокого понимания работы с запросами.
Она удобна в случае, если нам необходимо менять текст запроса динамически в зависимости от параметров системы, выбора пользователя, результата предыдущего запроса.
Для модификации текста имеющегося запроса, этот текст необходимо установить для схемы и получить обратно после модификации. Для этого используется код вида:
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);
//Тут наши комманды модификации запроса
Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();
Объектная модель запроса включает основной объект "Схема запроса" и около 50 связанных с ним подчиненных объектов, коллекций и специфичных типов данных. Поначалу ориентироваться в этом наборе объектов достаточно сложно.
Чтобы понять общую структуру схемы запроса открываем нужный раздел СП и загоняем все связи между объектами в графопостроитель.
Получается такой вот граф.
Не могу сказать, что он очень понятный, но общую идею отображает. Удобно подглядывать при анализе запроса.
В графе обозначены:
Желтым - объектные сущности схемы запроса;
Красным - коллекции объектов;
Зеленым - стандартные типы 1С (строка, число, булево);
Бирюзовым - примитивные типы, специфичные для схемы запроса;
Наиболее удобна схема запроса для модификаций готового запроса, на она также позволяет создать текст запроса с нуля.
Для примера рассмотрим создания с нуля пакета запроса, аналогичного запросу из "Справочной схемы"
ВЫБРАТЬ РАЗРЕШЕННЫЕ
Товары.Ссылка КАК Номенклатура,
Закупки.Период КАК Период,
ЕСТЬNULL(Закупки.СуммаОборот, 0) КАК СуммаЗакупок,
0 КАК СуммаПродаж
ПОМЕСТИТЬ ТаблицаОбороты
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Закупки.Обороты(&Начало, &Окончание, Месяц) КАК Закупки
ПО Закупки.Номенклатура = Товары.Ссылка
ГДЕ
НЕ Товары.ЭтоГруппа
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 100
Товары.Ссылка,
Продажи.Период,
0,
ЕСТЬNULL(Продажи.СуммаОборот, 0)
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(&Начало, &Окончание, Месяц) КАК Продажи
ПО Продажи.Номенклатура = Товары.Ссылка
ГДЕ
НЕ Товары.ЭтоГруппа
ИНДЕКСИРОВАТЬ ПО
Номенклатура,
Период
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаОбороты.Номенклатура КАК Номенклатура,
ТаблицаОбороты.Период КАК Период,
СУММА(ТаблицаОбороты.СуммаЗакупок) КАК СуммаЗакупок,
СУММА(ТаблицаОбороты.СуммаПродаж) КАК СуммаПродаж
ИЗ
ТаблицаОбороты КАК ТаблицаОбороты
СГРУППИРОВАТЬ ПО
ТаблицаОбороты.Номенклатура,
ТаблицаОбороты.Период
ИМЕЮЩИЕ
СУММА(ТаблицаОбороты.СуммаЗакупок) > 0
УПОРЯДОЧИТЬ ПО
ТаблицаОбороты.Номенклатура.Наименование,
Период
ИТОГИ
СУММА(СуммаЗакупок),
СУММА(СуммаПродаж)
ПО
ОБЩИЕ,
Номенклатура ТОЛЬКО ИЕРАРХИЯ
;
////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ТаблицаОбороты
Проанализируем пакет запросов.
Пакет представляет из себя набор из трех запросов.
В первом запросе данные выбираются из ИБ двумя оперататорами (запросы по закупкам и продажам), каждый из которых использует два источника (справочник "Номенклатура" и соответствующий регистр накопления). Данные объединятся из двух операторов и помещаются во временную таблицу на сервере.
Во втором запросе мы получаем данные из временной таблицы, группируем их и получаем результат для обработки на сервере 1С.
Третий запрос служит для уничтожения временной таблицы, сформированной первым запросом.
Начнем программное создание пакета запросов.
Для разработки кода воспользуемся деревом запроса. По нему удобно определять пути к данным. Желательно периодически проверять получившийся текст запроса после модификаций кода.
Для начала создадим объект "СхемаЗапроса".
СхемаЗапроса = Новый СхемаЗапроса;
Созданная схема запроса уже содержит один пакет и один оператор выбора.
Для удобства работы сохраним их в отдельные переменные.
ЗапросВыбораИзИБ = СхемаЗапроса.ПакетЗапросов[0];
ОператорВыбораЗакупок = ЗапросВыбораИзИБ.Операторы[0];
Добавляем источники в первый оператор выбора.
Для этого используем метод коллекции источников "Добавить()". В параметрах метода указываем имя добавляемой таблицы ее псевдоним, по которму будем обращаться к ней в дальнейшем.
В качестве добавляемсой таблицы можно использовать либо имя таблицы, либо ссылку на неё в коллекции доступных таблиц.
ИсточникНоменклатура = ОператорВыбораЗакупок.Источники.Добавить("Справочник.Номенклатура","Товары");
ИсточникЗакупки = ОператорВыбораЗакупок.Источники.Добавить("РегистрНакопления.Закупки.Обороты","Закупки");
По умолчанию второй источник добавляется с левым соединение к первому.
Нам нужно обратное сединение. Меняем тип соединения.
ИсточникЗакупки.Соединения[0].ТипСоединения = ТипСоединенияСхемыЗапроса.ПравоеВнешнее;
Параметры таблиц:
Для каждой добавленной в качестве источника таблицы мы можем задать дополнительные параметры.
Коллекция параметров заполняется автоматически при добавлении таблицы в зависимости от типа таблицы.
Добавить в неё параметр вручную нельзя, можно лишь установить значение имеющегося параметра.
Таблица "Справочник.Номенклатура" это простая таблица справочника. У нее параметров нет.
Таблица "РегистрНакопления.Закупки.Обороты" это таблица оборотов регистра накопления.
Согласно СП, у неё есть 4 параметра: начало периода, конец периода, периодичность, условие.
Нам необходимо установить первые 3 параметра:
ИсточникЗакупки.Источник.Параметры[0].Выражение = Новый ВыражениеСхемыЗапроса("&Начало") ;
ИсточникЗакупки.Источник.Параметры[1].Выражение = Новый ВыражениеСхемыЗапроса("&Окончание") ;
ИсточникЗакупки.Источник.Параметры[2].Выражение = Новый ВыражениеСхемыЗапроса("Месяц") ;
Укажем колонки, которые необходимо выбрать из перечисленных таблиц.
Для этого добавляем поля в коллекцию выбираемых полей оператора выбора.
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("Товары.Ссылка");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("Закупки.Период");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("ЕСТЬNULL(Закупки.СуммаОборот, 0)");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("0");
Укажем на уровне запроса вцелом псевдонимы для выбираемых колонок:
Обратите внимание, что колонки таблиц выбираем для каждого подзапроса объединения, имена колонкам присваиваем вцелом для коллекции "Колонки" на уровне запроса пакета.
ЗапросВыбораИзВТ.Колонки[0].Псевдоним = "Номенклатура";
ЗапросВыбораИзВТ.Колонки[1].Псевдоним = "Период";
ЗапросВыбораИзВТ.Колонки[2].Псевдоним = "СуммаЗакупок";
ЗапросВыбораИзВТ.Колонки[3].Псевдоним = "СуммаПродаж";
Добавим условие на выбор данных
ОператорВыбораПродаж.Отбор.Добавить("НЕ Товары.ЭтоГруппа");
Всё аналогично добавляем для второй части запроса.
Сопоставление колонок:
У нас в каждом операторе выбора выбирается 4 поля (элемент справочника "Номенклатура", дата и два числовых поля).
При объединении колонок из двух операторов выбора колонки из справочника и даты система соспоставит сама.
Числовых колонок две. Схема может самостоятельно сопоставить их с колонками первого запроса неверно.
Указываем, какой колонке таблицы результата какое выражение соответствует.
ЗапросВыбораИзИБ.Колонки[2].Поля.Установить(1,ВыражениеЗакупки);
ЗапросВыбораИзИБ.Колонки[3].Поля.Установить(1,ВыражениеПродажи);
Все аналогично повторяем для второго запроса пакета.
Из отличий, тут используется отбор по итоговым значения вида "ИМЕЮЩИЕ".
Такое условие добавляется аналогично обычному отбору на детальные записи.
Схема сама определит, в какой раздел условий поместить наше в зависимости от использования функций группировки.
ОператорВыбрать.Отбор.Добавить("СУММА(ТаблицаОбороты.СуммаЗакупок) > 0");
Последним шагом добавляем запрос на уничтожение таблицы данных
ЗапросУничтоженияВТ = СхемаЗапроса.ПакетЗапросов.Добавить(Тип("ЗапросУничтоженияТаблицыСхемыЗапроса"));
ЗапросУничтоженияВТ.ИмяТаблицы = "ТаблицаОбороты";
А также выставляем дополнительные свойства запросов:
ЗапросВыбораИзИБ.ТаблицаДляПомещения = "ТаблицаОбороты";
ЗапросВыбораИзИБ.ВыбиратьРазрешенные = Истина;
Итоговый полный вариант формирования запроса:
//Создание схемы запроса
СхемаЗапроса = Новый СхемаЗапроса;
ЗапросВыбораИзИБ = СхемаЗапроса.ПакетЗапросов[0];
//Установка свойств запроса
ЗапросВыбораИзИБ.ТаблицаДляПомещения = "ТаблицаОбороты";
ЗапросВыбораИзИБ.ВыбиратьРазрешенные = Истина;
//Добавляем операторы выбора первого запроса пакета
ОператорВыбораЗакупок = ЗапросВыбораИзИБ.Операторы[0];
ИсточникНоменклатура = ОператорВыбораЗакупок.Источники.Добавить("Справочник.Номенклатура","Товары");
//Добавляем запрос выбора из регистра закупок
ИсточникЗакупки = ОператорВыбораЗакупок.Источники.Добавить("РегистрНакопления.Закупки.Обороты","Закупки");
ИсточникЗакупки.Источник.Параметры[0].Выражение = Новый ВыражениеСхемыЗапроса("&Начало") ;
ИсточникЗакупки.Источник.Параметры[1].Выражение = Новый ВыражениеСхемыЗапроса("&Окончание") ;
ИсточникЗакупки.Источник.Параметры[2].Выражение = Новый ВыражениеСхемыЗапроса("Месяц") ;
//Меняем тип соединения
ИсточникЗакупки.Соединения[0].ТипСоединения = ТипСоединенияСхемыЗапроса.ПравоеВнешнее;
//Указываем выбираемые поля
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("Товары.Ссылка");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("Закупки.Период");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("ЕСТЬNULL(Закупки.СуммаОборот, 0)");
ОператорВыбораЗакупок.ВыбираемыеПоля.Добавить("0");
//Указываем спевдонимы для выбранных полей
ЗапросВыбораИзИБ.Колонки[0].Псевдоним = "Номенклатура";
ЗапросВыбораИзИБ.Колонки[1].Псевдоним = "Период";
ЗапросВыбораИзИБ.Колонки[2].Псевдоним = "СуммаЗакупок";
ЗапросВыбораИзИБ.Колонки[3].Псевдоним = "СуммаПродаж";
//Добавляем отбор
ОператорВыбораЗакупок.Отбор.Добавить("НЕ Товары.ЭтоГруппа");
///////////////////////
//Выбираем данные о продажах
ОператорВыбораПродаж = ЗапросВыбораИзИБ.Операторы.Добавить();
ИсточникНоменклатура = ОператорВыбораПродаж.Источники.Добавить("Справочник.Номенклатура","Товары");
ОператорВыбораПродаж.ВыбираемыеПоля.Добавить("Товары.Ссылка");
//Добавляем источник РН и устанавливаем параметры
ИсточникПродажи =ОператорВыбораПродаж.Источники.Добавить("РегистрНакопления.Продажи.Обороты","Продажи");
ИсточникПродажи.Источник.Параметры[0].Выражение = Новый ВыражениеСхемыЗапроса("&Начало") ;
ИсточникПродажи.Источник.Параметры[1].Выражение = Новый ВыражениеСхемыЗапроса("&Окончание") ;
ИсточникПродажи.Источник.Параметры[2].Выражение = Новый ВыражениеСхемыЗапроса("Месяц") ;
ИсточникПродажи.Соединения[0].ТипСоединения = ТипСоединенияСхемыЗапроса.ПравоеВнешнее;
//Указываем отбираемые поля и устанавливаем для числовых полей соответствие с полями первого запроса
ОператорВыбораПродаж.ВыбираемыеПоля.Добавить("Продажи.Период");
ВыражениеЗакупки = ОператорВыбораПродаж.ВыбираемыеПоля.Добавить("0");
ВыражениеПродажи = ОператорВыбораПродаж.ВыбираемыеПоля.Добавить("ЕСТЬNULL(Продажи.СуммаОборот, 0)");
ЗапросВыбораИзИБ.Колонки[2].Поля.Установить(1,ВыражениеЗакупки);
ЗапросВыбораИзИБ.Колонки[3].Поля.Установить(1,ВыражениеПродажи);
//Добавляем отбор
ОператорВыбораПродаж.Отбор.Добавить("НЕ Товары.ЭтоГруппа");
//Индексируем данные
ЗапросВыбораИзИБ.Индекс.Добавить(ЗапросВыбораИзИБ.Колонки[0]);
ЗапросВыбораИзИБ.Индекс.Добавить(ЗапросВыбораИзИБ.Колонки[1]);
//Устанавливаем параметры выбора данных
ОператорВыбораПродаж.ВыбиратьРазличные = Истина;
ОператорВыбораПродаж.КоличествоПолучаемыхЗаписей = 100;
////////////////
//Второй пакет запроса
ЗапросВыбораИзВТ = СхемаЗапроса.ПакетЗапросов.Добавить();
ОператорВыбрать = ЗапросВыбораИзВТ.Операторы[0];
//Устанавливаем сформированную в прошлом запросе временную таблицу как источник
Источник = ОператорВыбрать.Источники.Добавить("ТаблицаОбороты","ТаблицаОбороты");
ОператорВыбрать.ВыбираемыеПоля.Добавить("ТаблицаОбороты.Номенклатура");
ОператорВыбрать.ВыбираемыеПоля.Добавить("ТаблицаОбороты.Период");
ОператорВыбрать.ВыбираемыеПоля.Добавить("СУММА(ТаблицаОбороты.СуммаЗакупок)");
ОператорВыбрать.ВыбираемыеПоля.Добавить("СУММА(ТаблицаОбороты.СуммаПродаж)");
//Условие отбора
ОператорВыбрать.Отбор.Добавить("СУММА(ТаблицаОбороты.СуммаЗакупок) > 0");
//Устанавливаем псевдонимы колонок
ЗапросВыбораИзВТ.Колонки[0].Псевдоним = "Номенклатура";
ЗапросВыбораИзВТ.Колонки[1].Псевдоним = "Период";
ЗапросВыбораИзВТ.Колонки[2].Псевдоним = "СуммаЗакупок";
ЗапросВыбораИзВТ.Колонки[3].Псевдоним = "СуммаПродаж";
//Порядок сортировки данных
ЗапросВыбораИзВТ.Порядок.Добавить(ЗапросВыбораИзВТ.Операторы[0].Источники[0].Источник.ДоступныеПоля[0].Поля[6]);
ЗапросВыбораИзВТ.Порядок.Добавить(ЗапросВыбораИзВТ.Колонки[1]);
//Итоги запроса
ИтогНоменклатура = ЗапросВыбораИзВТ.КонтрольныеТочкиИтогов.Добавить(ЗапросВыбораИзВТ.Колонки[0]);
ИтогНоменклатура.ТипКонтрольнойТочки = ТипКонтрольнойТочкиСхемыЗапроса.ТолькоИерархия;
ЗапросВыбораИзВТ.ОбщиеИтоги =Истина;
ЗапросВыбораИзВТ.ВыраженияИтогов.Добавить(ЗапросВыбораИзВТ.Колонки[2]);
ЗапросВыбораИзВТ.ВыраженияИтогов.Добавить(ЗапросВыбораИзВТ.Колонки[3]);
////////////////
//Последний запрос пакета - удаление временной таблицы
ЗапросУничтоженияВТ = СхемаЗапроса.ПакетЗапросов.Добавить(Тип("ЗапросУничтоженияТаблицыСхемыЗапроса"));
ЗапросУничтоженияВТ.ИмяТаблицы = "ТаблицаОбороты";
Выполнив этот набор команд мы получаем тот же запрос, который ранее получили конструктором.
Явно видно, что программное создание гораздо сложнее, чем текстовое.
Возникает вопрос, в чем смылс морочиться с программным создание вместо удобного конструирования.
Если этот запрос больше не изменится, то смысла нет никакого.
Плюшки появляются только в случае, если нам необходимо этот запрос модифицировать дальше в зависимости от настроек.
Рассмотрим несколько примеров модификация нашего пакета из 3х запросов:
Пример 1.
Допустим, у нас есть переменные "Организация" и "Склад". И в случае, если они заполнены, нам необходимо добавить в отбор данных условия на эти переменные.
При работе с текстом нам придется вклиниваться в текст запроса и писать сложное условия вида "Если заполнен скалад, то добавить условие". при чем разрывать в нескольких местах и комбинировать варианты заполнены и склад и организация, заполнен только склад, заполнена только организация, ничего не заполнено.
После такой модификации открыть запрос конструктором будет и невозможно и дальнейшая его модификация сильно затруднена.
При программной работе с данными мы просто добавляем команды:
Если ЗначениеЗаполнено(Организация) Тогда
ОператорВыбораЗакупок.Отбор.Добавить("Закупки.Организация = &Организация");
ОператорВыбораПродаж.Отбор.Добавить("Продажи.Организация = &Организация");
КонецЕсли;
Если ЗначениеЗаполнено(Склад) Тогда
ОператорВыбораЗакупок.Отбор.Добавить("Закупки.Склад = &Склад");
ОператорВыбораПродаж.Отбор.Добавить("Продажи.Склад = &Склад");
КонецЕсли;
Пример 2.
Нам нужно отобрать товары, для которых последняя цена выше 1000руб.
Т.е. необходимо
1. Добавить в текст запроса выбор во временную таблицу из регистра цен номенклатуры, по которой цены выше 1000руб.
2. Добавить при выборе данных условия по этой временной таблице в оба запроса выбора данных (закупки и продажи).
Как вклиниваться в текстовый запрос для выполнения этих действий, вы пожете представить самостоятельно.
Программно мы просто добавляем строки кода:
//Добавляем временную таблицу
ЗапросИзРегистраЦен = СхемаЗапроса.ПакетЗапросов.Добавить();
//Настраиваем временную таблицу
ЗапросИзРегистраЦен.ТаблицаДляПомещения = "ВТ_ЦеныНоменклатуры";
ОператорВыбрать = ЗапросИзРегистраЦен.Операторы[0];
Источник = ОператорВыбрать.Источники.Добавить("РегистрСведений.ЦеныНоменклатуры.СрезПоследних","ЦеныНоменклатурыСрезПоследних");
ОператорВыбрать.ВыбираемыеПоля.Добавить("ЦеныНоменклатурыСрезПоследних.Номенклатура");
ОператорВыбрать.Отбор.Добавить("ЦеныНоменклатурыСрезПоследних.Цена > &Цена");
//Сдвигаем новую табличку перед запросами выбора данных
СхемаЗапроса.ПакетЗапросов.Сдвинуть(СхемаЗапроса.ПакетЗапросов.Индекс(ЗапросИзРегистраЦен),0);
//Добавляем условия в исходные запросы
ОператорВыбораЗакупок.Отбор.Добавить("Закупки.Номенклатура В (ВЫБРАТЬ ВТ_ЦеныНоменклатуры.Номенклатура ИЗ ВТ_ЦеныНоменклатуры КАК ВТ_ЦеныНоменклатуры)");
ОператорВыбораПродаж.Отбор.Добавить("Продажи.Номенклатура В (ВЫБРАТЬ ВТ_ЦеныНоменклатуры.Номенклатура ИЗ ВТ_ЦеныНоменклатуры КАК ВТ_ЦеныНоменклатуры)");
ИМХО, даже для этих примеров программная работа с запросом удобнее, чем прямая работа с текстом.
При этом учтем, что данные варианты модификаций все-таки достаточно простые.
С усложнением вариантов модификаций, увеличением количества запросов в пакете, выбором различных модификаций в зависимости от условий (например, добавление условий либо по регистру цен, либо по видам номенклатуры, либо по планам производства) программная работа выглядит всё более удобной по сравнению с работой с текстовой строкой.
Попрактиковаться с запросами можно с использованием обработки Дерево объектной модели схемы запроса.Она удобна для разработки комманд модификации имеющегося запроса. В ней же есть несколько примеров модификации кода запроса и граф схемы типов запроса.
з.ы. Всё выше написанное всего лишь моё личное понимание темы. Возможно, где-то ошибаюсь. Комментарии и уточнения приветствуются.
upd: Еще один небольшой пример использования схемы запроса. Формирование запроса, выполняющего поиск задвоенных значений предопределенных данных. Без обращения к метаданным формирует один общий запрос ко всем справочникам, планам счетов, ПВХ, ПВР вцелом по конфигурации. Используется в обработке Установка, просмотр и поиск задвоенных предопределенных значений справочников, планов счетов, ПВХ, ПВР.
СхемаЗапроса = Новый СхемаЗапроса;
КоллекцияОператоры = СхемаЗапроса.ПакетЗапросов[0].Операторы;
Для каждого ГруппаТаблиц Из СхемаЗапроса.ПакетЗапросов[0].ДоступныеТаблицы Цикл
Если ГруппаТаблиц.Представление = "Справочники"
ИЛИ ГруппаТаблиц.Представление = "ПланыСчетов"
ИЛИ ГруппаТаблиц.Представление = "ПланыВидовРасчета"
ИЛИ ГруппаТаблиц.Представление = "ПланыВидовХарактеристик" Тогда
Для каждого Таблица Из ГруппаТаблиц.Состав Цикл
Для каждого ПолеТаблицы Из Таблица.Поля Цикл
Если ПолеТаблицы.Имя = "ИмяПредопределенныхДанных" Тогда
НовыйОператор = КоллекцияОператоры.Добавить();
НовыйИсточник = НовыйОператор.Источники.Добавить(Таблица,"СправочникИмя");
НовыйОператор.ВыбираемыеПоля.Добавить(""""+Таблица.Имя+"""");
НовыйОператор.ВыбираемыеПоля.Добавить("КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СправочникИмя.ИмяПредопределенныхДанных)" );
НовыйОператор.Группировка.Добавить("СправочникИмя.ИмяПредопределенныхДанных");
НовыйОператор.Отбор.Добавить("СправочникИмя.Предопределенный");
НовыйОператор.Отбор.Добавить("КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СправочникИмя.Ссылка) > 1");
Продолжить;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;