В практике разработки на платформе 1С:Предприятие часто возникает задача пронумеровать записи непосредственно в тексте запроса. Это может потребоваться для формирования печатных форм, вывода специфических отчетов или реализации сложных алгоритмов обработки данных. Хотя платформа ориентирована на работу с наборами данных, а не с порядковыми индексами, существует несколько проверенных способов решения этой задачи. Разберем их подробно.
Этот способ считается классическим и работает на всех версиях платформы 1С:Предприятие 8. Суть метода заключается в том, что для каждой записи основной таблицы мы подсчитываем количество записей в этой же таблице, которые «меньше или равны» текущей по определенному уникальному полю (обычно по Ссылка или комбинации Дата + Ссылка).
Рассмотрим логику реализации:
Справочник.Номенклатура).КОЛИЧЕСТВО() для подсчета уникальных ссылок из присоединенной таблицы.Проанализируем пример кода для этого метода:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
КОЛИЧЕСТВО(Ном.Ссылка) КАК ПорядковыйНомер
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
ПО Номенклатура.Ссылка >= Ном.Ссылка
ГРУППИРОВАТЬ ПО
Номенклатура.Ссылка
УПОРЯДОЧИТЬ ПО
ПорядковыйНомер
Важные нюансы метода:
Нужно понимать, что производительность данного запроса падает в квадратичной зависимости ($O(n^2)$) от количества записей. Если в таблице 100 элементов, запрос отработает мгновенно. Однако для 10 000 записей количество операций сравнения в базе данных может достичь десятков миллионов, что приведет к значительным задержкам или ошибке TimeOut SQL-сервера. Всегда используйте индексированные поля для соединения.
Также стоит учесть проблему дублей. Если поле, по которому идет сравнение (например, Дата), содержит одинаковые значения для разных строк, функция КОЛИЧЕСТВО() вернет одинаковый номер для этих строк. Чтобы избежать этого, в условии соединения необходимо использовать уникальный идентификатор (Ссылка) как дополнительный критерий.
Начиная с версии платформы 8.3.13.2100, разработчикам стал доступен более современный и производительный инструмент — встроенная функция запроса АВТОНОМЕРЗАПИСИ(). Это наиболее правильный способ решения задачи в современных конфигурациях.
Однако у этой функции есть жесткие правила использования, которые мы сейчас разберем:
ПОМЕСТИТЬ.УПОРЯДОЧИТЬ ПО.Посмотрим на пример реализации через пакетный запрос:
// Шаг 1: Формируем пронумерованную временную таблицу
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ_ПронумерованныеДанные
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
Номенклатура.Наименование;
// Шаг 2: Выбираем данные из временной таблицы
ВЫБРАТЬ
ВТ_ПронумерованныеДанные.НомерСтроки КАК Номер,
ВТ_ПронумерованныеДанные.Ссылка КАК Ссылка
ИЗ
ВТ_ПронумерованныеДанные КАК ВТ_ПронумерованныеДанные
УПОРЯДОЧИТЬ ПО
Номер
Данный метод работает значительно быстрее «самосоединения», так как нумерация выполняется линейно при записи данных во временную таблицу в памяти или в tempdb СУБД.
Если ваша задача заключается в выводе нумерованного списка в отчет или экранную форму, то самым простым и эффективным решением будет использование возможностей СКД. Это позволяет не усложнять текст запроса и не нагружать сервер лишними вычислениями.
Выясним, какие инструменты СКД нам доступны:
№ п/п. Платформа сама пронумерует строки при выводе результата.ПорядковыйНомер(). Это удобно, если номер нужен для дальнейших расчетов внутри схемы.Этот подход является предпочтительным с точки зрения архитектуры 1С, так как разделяет логику получения данных и логику их визуального представления.
В случаях, когда номер нужен для последующей сложной логики в коде на встроенном языке, зачастую проще и быстрее пронумеровать строки после выполнения запроса. Проанализируем этот сценарий:
РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультата = РезультатЗапроса.Выгрузить();
ТаблицаРезультата.Колонки.Добавить("Номер", Новый ОписаниеТипов("Число"));
Для Каждого Строка Из ТаблицаРезультата Цикл
Строка.Номер = ТаблицаРезультата.Индекс(Строка) + 1;
КонецЦикла;
Такой подход работает в оперативной памяти и, как правило, быстрее любого сложного запроса с соединениями на больших объемах данных.
Мы рассмотрели различные варианты нумерации. Выбор конкретного метода зависит от ваших условий:
АВТОНОМЕРЗАПИСИ() через временную таблицу.№ п/п).ТаблицеЗначений.Помните, что избыточная сложность запроса может негативно сказаться на масштабируемости системы, поэтому всегда выбирайте наиболее легкий инструмент для решения вашей задачи.