Как в выгруженной таблице запроса 1С получить колонку Номер строки

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

Почему в выгруженной таблице значений нет номера строки

При выполнении метода Выгрузить() объекта РезультатЗапроса платформа 1С формирует колонки объекта ТаблицаЗначений строго на основании полей, указанных в секции ВЫБРАТЬ. В отличие от табличных частей документов или справочников, у объекта ТаблицаЗначений нет встроенного системного реквизита НомерСтроки.

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

Рассмотрим основные способы решения этой задачи, их особенности и влияние на производительность.

Способ 1. Добавление колонки в запросе и заполнение в цикле (Рекомендуемый способ)

Наиболее эффективным и безопасным подходом с точки зрения производительности является сочетание подготовки колонки в самом запросе и последующего быстрого обхода таблицы по индексу.

Разберем по шагам алгоритм действий:

  1. В секции ВЫБРАТЬ языка запросов сразу добавляем числовое поле-заглушку, например 0 КАК НомерСтроки. В этом случае выгруженная ТаблицаЗначений сразу получит колонку с нужным именем и типом данных Число, и нам не придется вызывать метод ТЗ.Колонки.Добавить().
  2. После выполнения запроса выгружаем результат в таблицу значений и проставляем номера строк в цикле по индексу.

Проанализируем пример кода 1С для этого решения:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	0 КАК НомерСтроки,
    |	Номенклатура.Ссылка КАК Номенклатура
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура";

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

Для Индекс = 0 По ТЗ.Количество() - 1 Цикл
    ТЗ[Индекс].НомерСтроки = Индекс + 1;
КонецЦикла;

Важный момент по производительности: заполнение по индексу выполняется с вычислительной сложностью $O(N)$, где $N$ — количество строк. Не используйте метод ТЗ.Индекс(Стр) внутри обхода Для Каждого Строка Из ТЗ Цикл, так как вызов Индекс() на каждом шаге выполняет повторный поиск с начала таблицы, что замедляет работу алгоритма до $O(N^2)$.

Способ 2. Использование Системы компоновки данных (СКД)

Если задача заключается в формировании отчета или выводе данных пользователю, выгоднее задействовать механизм СКД. В Системе компоновки данных предусмотрено системное поле НомерПоПорядку (или СистемныеПоля.НомерПоПорядку).

Рассмотрим, чем этот подход отличается от обычного запроса:

  1. Вам не нужно писать код обхода таблицы или усложнять текст запроса.
  2. При выгрузке или выводе результата СКД автоматически рассчитывает порядковые номера записей на уровне процессора компоновки данных.
  3. Это полностью исключает необходимость написания кода постобработки.

Способ 3. Вычисление номера в тексте запроса (Самосоединение)

Существует возможность получить нумерацию строк прямо в тексте запроса с помощью левого самосоединения временной таблицы. Однако у этого способа есть существенные ограничения.

Выясним механику работы алгоритма:

  1. Исходные данные помещаются во временную таблицу ВТ_Данные.
  2. Выполняется левое соединение ВТ_Данные сама с собой по условию ВТ1.УникальноеПоле >= ВТ2.УникальноеПоле.
  3. Применяется группировка по полям первого источника с подсчетом КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ2.УникальноеПоле).

Посмотрим на пример текста запроса:


ВЫБРАТЬ
	Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ВТ_Данные
ИЗ
	Справочник.Номенклатура КАК Номенклатура
;

ВЫБРАТЬ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т2.Номенклатура) КАК НомерСтроки,
	Т1.Номенклатура КАК Номенклатура
ИЗ
	ВТ_Данные КАК Т1
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Данные КАК Т2
		ПО Т1.Номенклатура >= Т2.Номенклатура
ГРУППИРОВАТЬ ПО
	Т1.Номенклатура

Ограничения этого способа:

  1. Поле соединения должно быть строго уникальным. Если в выборке присутствуют дубли, одинаковые записи получат идентичный порядковый номер.
  2. Сложность вычислений составляет $O(N^2)$. На таблицах объемом более нескольких тысяч строк вычисление такого запроса на стороне СУБД приведет к высокому падению производительности и нагрузке на сервер.

Способ 4. Вывод номера на форме без изменения ТаблицыЗначений

Если нумерация нужна исключительно для визуального отображения пользователю в интерфейсе (в элементе формы ТаблицаФормы), добавлять колонку в сам объект ТаблицаЗначений на сервере вовсе не требуется.

Проанализируем этот вариант:

  1. При выводе таблицы на форму можно использовать стандартное отображение номеров строк элемента управления.
  2. В элементах формы визуальный порядок строк поддерживается автоматически встроенными средствами интерфейса.

Этот способ экономит оперативную память сервера и ресурс процессора, исключая лишние операции по нумерации данных в коде.

← На главную