К статье
Практический материал

Разработка и Конфигурация · 10 мин

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

Как пронумеровать строки результата запроса в 1С: функция АВТОНОМЕРЗАПИСИ, нумерация при обходе выборки, нумерация в таблице значений и СКД. Примеры кода и типичные ошибки.

Нумерация строк результата запроса — частая задача при разработке отчётов, печатных форм и обработок в 1С. Номер строки нужен для вывода в табличный документ, для упорядочивания данных при обмене, для контроля количества записей и для решения задач ранжирования. В языке запросов 1С нет прямого аналога функции ROW_NUMBER из классического SQL, поэтому задачу решают несколькими способами.

Выбор способа зависит от того, где именно нужен номер: непосредственно в тексте запроса, при обходе выборки в коде, в таблице значений или в схеме компоновки данных. У каждого варианта есть свои ограничения по производительности и применимости, и важно понимать их различия, чтобы не получить неожиданный порядок нумерации или лишнюю нагрузку на сервер.

Способы нумерации строк: какой выбрать

Существует четыре рабочих подхода. Первый — функция АВТОНОМЕРЗАПИСИ() прямо в запросе: просто, но без гарантированной связи с сортировкой и без нумерации по группам. Второй — счётчик при обходе выборки в коде: полный контроль над порядком и группами, но требует программной обработки результата.

Третий способ — добавить колонку в таблицу значений после выгрузки запроса и заполнить её в цикле. Четвёртый — использовать возможности СКД: вычисляемые поля или функцию НомерПоПорядку в макете. Для отчётов на СКД это обычно самый чистый вариант, так как нумерация выполняется на этапе формирования, а не выборки данных.

Сравнение вариантов

АВТОНОМЕРЗАПИСИ() в запросе

Быстро и без кода, но нумерация не привязана к УПОРЯДОЧИТЬ ПО и не сбрасывается по группам

Счётчик при обходе выборки

Полный контроль порядка и групп, подходит для печатных форм и обработок

Колонка в таблице значений

Удобно, когда результат передаётся дальше как ТЗ; требует дополнительного прохода по данным

Нумерация в СКД

Лучший вариант для отчётов: номер формируется при выводе, запрос не усложняется

Функция АВТОНОМЕРЗАПИСИ в тексте запроса

Встроенная функция АВТОНОМЕРЗАПИСИ() возвращает целое число — порядковый номер записи в результате запроса. Она указывается в списке полей выборки и не принимает аргументов. Это самый быстрый способ добавить номер строки, не выходя из конструктора запроса.

// Пример: нумерация списка товаров

ВЫБРАТЬ

АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,

Номенклатура.Ссылка КАК Товар,

Номенклатура.Наименование КАК Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

НЕ Номенклатура.ПометкаУдаления

Ключевое ограничение: функция нумерует записи в том порядке, в котором их фактически сформировал запрос, а не в порядке, заданном предложением УПОРЯДОЧИТЬ ПО. Если добавить сортировку по наименованию, номера могут распределиться не по возрастанию относительно отсортированного списка. Поэтому АВТОНОМЕРЗАПИСИ подходит, когда важен сам факт уникального номера, а не его соответствие визуальному порядку.

Ещё одно ограничение — функция не умеет нумеровать записи отдельно внутри групп. Если нужна нумерация «1, 2, 3» в каждом документе или в каждой категории, АВТОНОМЕРЗАПИСИ не поможет: потребуется обход выборки с иерархией или группировкой и программный счётчик.

Нумерация при обходе выборки в коде

Самый управляемый способ — объявить переменную-счётчик и увеличивать её в цикле обхода выборки. Порядок нумерации в этом случае полностью совпадает с порядком обхода, то есть с сортировкой запроса. Такой подход стандартен для печатных форм, где номер строки выводится в табличную часть документа.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| Товары.Количество КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка

|

|УПОРЯДОЧИТЬ ПО

| Товары.НомерСтроки";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Выборка = Запрос.Выполнить().Выбрать();

НомерСтроки = 0;

Пока Выборка.Следующий() Цикл

НомерСтроки = НомерСтроки + 1;

// Вывод НомерСтроки и данных в табличный документ

КонецЦикла;

Для нумерации внутри групп используют обход выборки с типом «ПоГруппировкам»: сначала обходятся группы, затем детальные записи внутри каждой, и счётчик сбрасывается при переходе к новой группе. Это решает задачу, недоступную для АВТОНОМЕРЗАПИСИ.

Порядок действий
  1. 1
    Сформируйте запрос с нужной сортировкой через УПОРЯДОЧИТЬ ПО
  2. 2
    Выполните запрос и получите выборку методом Выбрать()
  3. 3
    Объявите переменную-счётчик перед циклом
  4. 4
    Увеличивайте счётчик на единицу в начале каждой итерации
  5. 5
    Используйте значение счётчика при выводе строки
  6. 6
    Для нумерации по группам сбрасывайте счётчик при смене группы

Добавление колонки с номером в таблицу значений

Если результат запроса выгружается в таблицу значений и дальше передаётся в другую процедуру, на форму или в обмен данными, удобно добавить колонку «НомерСтроки» и заполнить её в цикле. Это делает номер частью структуры данных, а не временной переменной.

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

ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));

Номер = 0;

Для Каждого Строка Из ТаблицаРезультат Цикл

Номер = Номер + 1;

Строка.НомерСтроки = Номер;

КонецЦикла;

Перед заполнением таблицу можно отсортировать методом Сортировать() — тогда номера будут соответствовать нужному порядку. Учтите, что дополнительный проход по таблице требует времени: на очень больших выборках (сотни тысяч строк) это заметно, хотя для типовых прикладных задач накладные расходы невелики.

Нумерация строк в отчётах на СКД

В системе компоновки данных нумеровать строки в самом запросе обычно не нужно. СКД предоставляет собственные механизмы: автополе «НомерПоПорядку» в ресурсах и вычисляемых полях, а также системное поле, доступное при настройке структуры отчёта. Номер формируется на этапе вывода, поэтому он всегда соответствует итоговой сортировке и группировкам отчёта.

Чтобы вывести номер строки, добавьте в настройках отчёта поле «Номер по порядку» из списка доступных системных полей либо создайте вычисляемое поле. Если используется программная компоновка или макет, номер выводится через параметр области с инкрементом в процедуре вывода — по аналогии со счётчиком при обходе выборки.

Преимущество подхода в том, что запрос остаётся простым и быстрым, а нумерация корректно работает при любых пользовательских настройках отбора и сортировки. Это особенно важно для отчётов, которые конечные пользователи настраивают самостоятельно.

Если номер строки нужен только для отображения в отчёте, не добавляйте его в запрос вообще — используйте системное поле СКД. Каждое лишнее вычисление в запросе увеличивает нагрузку на СУБД, а пользовательская сортировка всё равно «сломает» заранее присвоенные номера.
ПЗ
Практическое замечание

Типичные ошибки и как их проверить

Самая распространённая ошибка — ожидать, что АВТОНОМЕРЗАПИСИ пронумерует записи в порядке сортировки. При добавлении УПОРЯДОЧИТЬ ПО номера «разъезжаются», и разработчик получает строки с номерами вперемешку. Решение — нумеровать при обходе выборки или в СКД.

Вторая ошибка — использовать номер строки как устойчивый идентификатор записи. Номер строки в запросе — это позиция в конкретном результате на конкретный момент; после изменения данных или отбора он изменится. Для идентификации записей используйте ссылку или уникальный идентификатор, а не порядковый номер.

Третья типичная проблема — попытка применить АВТОНОМЕРЗАПИСИ в запросе с итогами или в пакетном запросе и неожиданное поведение в итоговых строках. Проверяйте результат на тестовых данных с группировками, прежде чем использовать запрос в рабочем коде.

Типичные ошибки
01
Ожидание, что АВТОНОМЕРЗАПИСИ совпадёт с УПОРЯДОЧИТЬ ПО — номера не соответствуют визуальному порядку
02
Использование номера строки как постоянного идентификатора записи — после изменения данных связь теряется
03
Нумерация в запросе для отчёта СКД — лишняя работа, которая ломается при пользовательской сортировке
04
Забытый сброс счётчика при нумерации по группам — нумерация продолжается сквозной вместо сброса в каждой группе
Контрольные точки

Как проверить результат

Соответствие номера порядку строк
Норма

Номера идут 1, 2, 3... в том порядке, в котором выводятся строки

Тревожный признак

Номера перемешаны относительно сортировки

Нумерация внутри групп
Норма

В каждой группе нумерация начинается с 1

Тревожный признак

Нумерация сквозная по всем группам

Производительность
Норма

Запрос выполняется за приемлемое время на рабочем объёме данных

Тревожный признак

Добавление нумерации заметно замедлило выполнение

FAQ: частые вопросы о нумерации строк в запросе 1С

Можно ли пронумеровать строки внутри каждой группы одним запросом?

Штатной функции нумерации по группам в языке запросов 1С нет. Практические варианты: обход выборки с группировками и сброс счётчика в коде, либо соединение таблицы с самой собой с подсчётом количества записей «меньше текущей» — но такой приём сильно нагружает СУБД и оправдан только на малых объёмах. В отчётах СКД нумерация по группам решается настройкой структуры без изменения запроса.

Почему после добавления УПОРЯДОЧИТЬ ПО номера АВТОНОМЕРЗАПИСИ перепутались?

Функция присваивает номера в момент формирования результата, до применения сортировки. Порядок нумерации и порядок сортировки не связаны между собой. Если нужен номер, совпадающий с отсортированным порядком, присваивайте его при обходе выборки или в таблице значений после сортировки.

Как вывести номер строки в печатной форме документа?

Объявите переменную-счётчик перед циклом обхода выборки, увеличивайте её на единицу в каждой итерации и подставляйте значение в параметр области макета, например ОбластьСтрока.Параметры.НомерСтроки = НомерСтроки. В макете создайте ячейку с параметром этого имени.

Работает ли АВТОНОМЕРЗАПИСИ в динамических списках?

Нет, в динамических списках эта функция не поддерживается — запрос динамического списка имеет ограничения на используемые конструкции. Для нумерации в списке обычно используют оформление на уровне формы или выводят данные через отчёт на СКД.

Что лучше для больших выборок: нумерация в запросе или в коде?

АВТОНОМЕРЗАПИСИ выполняется на стороне СУБД и обычно не создаёт существенной нагрузки. Программный счётчик при обходе выборки тоже дёшев, так как это простая операция инкремента. Заметные потери возникают только при избыточных подходах — например, при нумерации через самосоединение таблиц или при лишнем проходе по большой таблице значений.

Можно ли начать нумерацию не с единицы?

Да. При программной нумерации просто инициализируйте счётчик нужным стартовым значением. Для АВТОНОМЕРЗАПИСИ в запросе можно добавить смещение арифметически: АВТОНОМЕРЗАПИСИ() + 100, если это допустимо в конкретной конструкции запроса.

Итог

Что важно запомнить

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