Как в запросе 1С выбрать данные из текста или массива?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При изучении языка запросов 1С начинающие разработчики часто сталкиваются с необходимостью обработать данные, которые еще не записаны в базу данных, но уже имеются в оперативной памяти (например, в массиве или таблице значений) или же вовсе должны быть сформированы «на лету» прямо в тексте самого запроса. В классическом SQL для этого существуют свои механизмы, однако в 1С есть свои специфические особенности и ограничения, которые мы подробно разберем в этой статье.

Метод 1: Использование внешних источников (Таблица Значений)

Рассмотрим ситуацию, когда у нас есть массив данных или готовая таблица в памяти, и нам нужно использовать ее в сложном запросе совместно с данными из информационной базы. Напрямую передать объект Массив в секцию ИЗ нельзя. Чтобы сделать данные доступными для запроса, их необходимо сначала поместить в объект ТаблицаЗначений, а затем передать как параметр.

Разберем по шагам, как это реализовать:

  1. Подготовка таблицы: Создаем таблицу значений, добавляем в нее колонки и типизируем их (это важно для корректной работы запроса).
  2. Передача в параметры: Используем метод УстановитьПараметр.
  3. Помещение во временную таблицу: В самом тексте запроса мы должны сначала «выбрать» данные из этого параметра и сохранить их во временную таблицу.

Посмотрим на пример кода, реализующий этот подход:


// 1. Подготовка данных в коде 1С:Предприятие
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Склад", Новый ОписаниеТипов("СправочникСсылка.Склады"));
ТаблицаДанных.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

// Заполнение (например, из массива или других данных)
НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.Склад = СкладСсылка;
НоваяСтрока.Количество = 10;

// 2. Выполнение запроса
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ВнешнийИсточник", ТаблицаДанных);
Запрос.Текст = 
"ВЫБРАТЬ
|    ВнешнийИсточник.Склад КАК Склад,
|    ВнешнийИсточник.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_ДанныеИзПамяти
|ИЗ
|    &ВнешнийИсточник КАК ВнешнийИсточник
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|    ВТ_ДанныеИзПамяти.Склад,
|    СУММА(ВТ_ДанныеИзПамяти.Количество) КАК ИтоговоеКоличество
|ИЗ
|    ВТ_ДанныеИзПамяти КАК ВТ_ДанныеИзПамяти
|СГРУППИРОВАТЬ ПО
|    ВТ_ДанныеИзПамяти.Склад";

РезультатЗапроса = Запрос.Выполнить();

Проанализируем этот пример: использование конструкции ПОМЕСТИТЬ является обязательным условием при работе с внешними таблицами значений. Без этого платформа не сможет связать локальные данные с таблицами СУБД.

Метод 2: Формирование данных прямо в тексте запроса (Константы и ОБЪЕДИНИТЬ ВСЕ)

Иногда требуется создать небольшую статичную таблицу прямо «в коде» запроса, не передавая ничего извне. В SQL это можно сделать простым перечислением в VALUES, а в 1С мы используем механизм объединения выборок из пустых источников (или параметров-констант).

Рассмотрим подробнее, как собрать таблицу из произвольных строк:


ВЫБРАТЬ
    ДАТАВРЕМЯ(2023, 1, 1) КАК Период,
    &Номенклатура1 КАК Номенклатура,
    10 КАК Количество
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    ДАТАВРЕМЯ(2023, 1, 15),
    &Номенклатура2,
    5
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    ДАТАВРЕМЯ(2023, 2, 01),
    &Номенклатура3,
    20

Выясним причину, почему это работает: первая секция ВЫБРАТЬ задает имена колонок и их типы. Все последующие секции ОБЪЕДИНИТЬ ВСЕ просто добавляют строки в этот виртуальный набор данных. Важный нюанс: в языке запросов 1С обязательна секция ИЗ, если вы выбираете поля из реальных таблиц. Однако, если вы выбираете только литералы (числа, строки, даты) или параметры, секция ИЗ может отсутствовать, что и позволяет нам «генерировать» данные из ничего.

Метод 3: Использование конструкции ЗНАЧЕНИЕ()

Для выбора специфических системных данных или предопределенных элементов конфигурации без передачи их через параметры, мы используем функцию ЗНАЧЕНИЕ(). Это позволяет сделать запрос более автономным.

Примеры использования этой конструкции:

Разберем ситуацию: вам нужно составить таблицу, где одна колонка будет содержать тип документа, а другая — его описание. Это можно сделать, комбинируя ЗНАЧЕНИЕ() и ОБЪЕДИНИТЬ ВСЕ.

Важные ограничения и рекомендации

Проанализируем технические лимиты, которые могут повлиять на стабильность вашей системы:

1. Ограничение на количество объединений: При использовании метода с ОБЪЕДИНИТЬ ВСЕ для создания больших таблиц (например, более 100-200 строк), вы можете столкнуться с ошибкой СУБД или крайне медленной работой. В таких случаях всегда лучше использовать ТаблицаЗначений как параметр (Метод 1).

2. Типизация данных: Платформа 1С определяет типы колонок по первому запросу в объединении. Если в первой секции вы укажете НЕОПРЕДЕЛЕНО в качестве значения, а во второй — ссылку, запрос может отработать некорректно. Старайтесь всегда явно указывать типы в первой выборке (например, через ВЫРАЗИТЬ или используя конкретные литералы).

3. Работа с Массивами: Как мы уже выяснили, массив нельзя использовать как таблицу. Однако его очень удобно использовать в условии фильтрации. Рассмотрим пример:


// Массив ссылок
МассивНоменклатуры = Новый Массив;
МассивНоменклатуры.Добавить(Ссылка1);
МассивНоменклатуры.Добавить(Ссылка2);

Запрос.УстановитьПараметр("СписокТоваров", МассивНоменклатуры);
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&СписокТоваров)";

4. Менеджер временных таблиц: Если вы планируете использовать созданную таблицу в нескольких разных запросах подряд, не забудьте инициализировать МенеджерВременныхТаблиц и передать его в объект Запрос. Это позволит хранить временные данные в течение всего сеанса работы программного кода.

Таким образом, мы рассмотрели основные способы «создания данных» внутри запроса. Выбор метода зависит от объема данных: для 1–5 строк подойдет ОБЪЕДИНИТЬ ВСЕ, для динамических списков — передача Таблицы Значений, а для системных констант — функция ЗНАЧЕНИЕ().

← На главную