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

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

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

Прикладные задачи поштучного разворачивания данных

Рассмотренный механизм размножения строк широко применяется в следующих практических сценариях:

  1. Печать ценников и этикеток: для печати индивидуальной этикетки или штрихкода на каждую физическую единицу товара из документа поступления или реализации.
  2. Генерация серийных номеров и маркировки: подготовка структуры под уникальные коды маркировки или упаковочные листы на основе общего количества в документе.
  3. Поштучный учет партий: разукомплектование товарных позиций или разбиение партий при учете индивидуальных экземпляров.

Способ 1. Соединение с временной таблицей натуральных чисел

Так как в языке запросов 1С отсутствуют встроенные функции генерации последовательностей (генераторы рядов чисел) и рекурсивные запросы, размножение строк выполняется путем внутреннего соединения исходных данных с таблицей чисел по условию ПорядковыйНомер <= Количество.

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


ВЫБРАТЬ 1 КАК Номер
ПОМЕСТИТЬ ВТ_Числа

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ 8
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ИсходныеДанные.Номенклатура КАК Номенклатура,
	1 КАК Количество,
	ВТ_Числа.Номер КАК НомерЗаписи
ИЗ
	ВТ_ИсходныеДанные КАК ИсходныеДанные
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Числа КАК ВТ_Числа
		ПО ВТ_Числа.Номер <= ИсходныеДанные.Количество

В результате этого запроса строка с количеством 8 соединится с числами от 1 до 8 и даст в итоговой выборке ровно 8 отдельных строк.

Способ 2. Передача таблицы чисел через параметр запроса

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

Посмотрим на пример программной реализации:


// 1. Создаем и заполняем таблицу чисел в коде 1С
ТЗЧисел = Новый ТаблицаЗначений;
ТЗЧисел.Колонки.Добавить("Число", Новый ОписаниеТипов("Число"));

МаксимальноеКоличество = 500; // Устанавливаем требуемый предел
Для Индекс = 1 По МаксимальноеКоличество Цикл
	НоваяСтрока = ТЗЧисел.Добавить();
	НоваяСтрока.Число = Индекс;
КонецЦикла;

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

Запрос.УстановитьПараметр("ТЗЧисел", ТЗЧисел);
Результат = Запрос.Выполнить();

Способ 3. Программная обработка результатов (без усложнения запроса)

Проанализируем ситуацию с точки зрения производительности СУБД. Генерация большого количества строк внутри запроса может создавать значительную нагрузку на сервер БД. Зачастую гораздо выгоднее выполнить простой агрегированный запрос, а разворачивание строк выполнить на стороне сервера 1С в цикле.

Рассмотрим пример алгоритма обработки выборки:


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	// Внутренний цикл по количеству из результата запроса
	Для Счетчик = 1 По Выборка.Количество Цикл
		// Выполняем действия для каждой штучной единицы
		// Например, формируем область печатной формы
	КонецЦикла;
КонецЦикла;

Ограничения и рекомендации по выбору решения

При выборе подходящего способа выясним ключевые ограничения платформы 1С:

  1. Большое количество соединений ОБЪЕДИНИТЬ ВСЕ существенно раздувает текст запроса и увеличивает время его компиляции на стороне СУБД.
  2. Декартово произведение крупных таблиц может привести к исчерпанию оперативной памяти и падению производительности.
  3. Для отчетов и печатных форм в Схеме компоновки данных (СКД) рекомендуется использовать встроенные настройки группировок и детальных записей вместо усложнения исходного запроса.
← На главную