В практике разработчика 1С часто возникают ситуации, когда стандартного текста запроса недостаточно или требуется динамически дополнить результат выборки данными, которые сложно или невозможно получить прямым SQL-запросом. Например, когда нужно добавить расчетные показатели, данные из внешних систем или результаты работы функций общего модуля. Разберем подробно, как можно модифицировать результат запроса, не внося правок в основной исходный текст вручную.
Самый простой и часто используемый метод — это выгрузка результата запроса в объект ТаблицаЗначений. После того как данные оказались в памяти, мы можем манипулировать ими как угодно: добавлять колонки, заполнять их в цикле или использовать метод ЗаполнитьЗначения().
Рассмотрим по шагам этот процесс:
Выгрузить().Колонки.Проанализируем пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
| РеализацияТоваровУслугТовары.Количество КАК Количество,
| РеализацияТоваровУслугТовары.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары";
РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультат = РезультатЗапроса.Выгрузить();
// Добавляем новое поле, которого не было в запросе
ТаблицаРезультат.Колонки.Добавить("ЦенаИзРегистра", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
// Заполняем поле программно
Для Каждого СтрокаТЗ Из ТаблицаРезультат Цикл
// Здесь может быть вызов функции или получение данных из другого источника
СтрокаТЗ.ЦенаИзРегистра = ПолучитьЦенуНоменклатуры(СтрокаТЗ.Номенклатура);
КонецЦикла;
Важный нюанс: Данный метод потребляет значительный объем оперативной памяти, так как вся выборка данных передается из СУБД в память приложения. Если в результате запроса сотни тысяч строк, лучше использовать другие подходы.
Если задача стоит в том, чтобы изменить сам запрос программно (добавить поля или соединения), не прибегая к строковым функциям типа СтрЗаменить(), следует использовать объект СхемаЗапроса. Это позволяет работать с запросом как с объектной моделью.
Выясним, как это работает. Мы загружаем текст запроса в схему, находим нужный пакет (или временную таблицу) и добавляем туда колонку. Платформа сама позаботится о правильном синтаксисе итогового текста.
Схема = Новый СхемаЗапроса;
Схема.УстановитьТекст(ТекстЗапроса);
ОператорВыбора = Схема.ПакетЗапросов[0].Операторы[0];
// Добавляем новое поле в список выбора
НовоеПоле = ОператорВыбора.ВыбираемыеПоля.Добавить("Номенклатура.Артикул");
// Можно задать псевдоним
НовоеПоле.Псевдоним = "АртикулНоменклатуры";
// Получаем обратно измененный текст
ТекстЗапроса = Схема.ПолучитьТекст();
Этот метод считается более профессиональным и безопасным, так как исключает ошибки синтаксиса при динамическом формировании текста запроса.
Если вам нужно модифицировать промежуточный результат (временную таблицу), рассмотрите вариант использования МенеджерВременныхТаблиц. Вместо того чтобы выгружать данные в ТЗ, вы можете выполнить второй запрос, используя тот же менеджер. Во втором запросе вы просто выбираете данные из первой временной таблицы и соединяете их с новыми источниками.
Разберем ситуацию на примере:
ВТ_Данные.МенеджерВременныхТаблиц.ВТ_Данные с другими таблицами базы данных.Посмотрим на пример логики:
МВТ = Новый МенеджерВременныхТаблиц;
Запрос1 = Новый Запрос("ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ...");
Запрос1.МенеджерВременныхТаблиц = МВТ;
Запрос1.Выполнить();
// Нам нужно добавить поле "Остаток", не меняя первый запрос
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МВТ;
Запрос2.Текст =
"ВЫБРАТЬ
| ВТ.Номенклатура,
| ВТ.Количество,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) КАК Остаток
|ИЗ
| ВТ_Данные КАК ВТ
|ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
|ПО ВТ.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура";
Результат = Запрос2.Выполнить();
Этот подход максимально эффективен, так как все вычисления и соединения происходят на стороне сервера базы данных, не нагружая клиентское приложение и сеть.
Иногда требуется "гибридный" метод: выгрузить данные, изменить их программно (например, применить сложную бизнес-логику), а затем снова использовать эти данные в других запросах. Для этого 1С позволяет передавать ТаблицаЗначений в качестве параметра запроса.
Проанализируем шаги:
УстановитьПараметр().Важное ограничение: При использовании ТЗ в запросе обязательно нужно типизировать все колонки таблицы, иначе запрос выдаст ошибку.
// Предположим, у нас есть ТЗ с данными
Запрос.УстановитьПараметр("ВнешниеДанные", МояТаблицаЗначений);
Запрос.Текст =
"ВЫБРАТЬ
| ВнешниеДанные.Номенклатура,
| ВнешниеДанные.СпецПоле
|ПОМЕСТИТЬ ВТ_ИзмененныеДанные
|ИЗ
| &ВнешниеДанные КАК ВнешниеДанные";
Подведем итоги нашего анализа. Выбор метода зависит от объема данных и сложности логики:
Используя эти инструменты, вы сможете гибко управлять структурой данных и обеспечивать высокую скорость работы ваших алгоритмов в 1С.