Разработка и Конфигурация · 10 мин
Как добавить номер строки в запросе 1С
Как пронумеровать строки результата запроса в 1С: функция АВТОНОМЕРЗАПИСИ, нумерация при обходе выборки, нумерация в таблице значений и СКД. Примеры кода и типичные ошибки.
Нумерация строк результата запроса — частая задача при разработке отчётов, печатных форм и обработок в 1С. Номер строки нужен для вывода в табличный документ, для упорядочивания данных при обмене, для контроля количества записей и для решения задач ранжирования. В языке запросов 1С нет прямого аналога функции ROW_NUMBER из классического SQL, поэтому задачу решают несколькими способами.
Выбор способа зависит от того, где именно нужен номер: непосредственно в тексте запроса, при обходе выборки в коде, в таблице значений или в схеме компоновки данных. У каждого варианта есть свои ограничения по производительности и применимости, и важно понимать их различия, чтобы не получить неожиданный порядок нумерации или лишнюю нагрузку на сервер.
Способы нумерации строк: какой выбрать
Существует четыре рабочих подхода. Первый — функция АВТОНОМЕРЗАПИСИ() прямо в запросе: просто, но без гарантированной связи с сортировкой и без нумерации по группам. Второй — счётчик при обходе выборки в коде: полный контроль над порядком и группами, но требует программной обработки результата.
Третий способ — добавить колонку в таблицу значений после выгрузки запроса и заполнить её в цикле. Четвёртый — использовать возможности СКД: вычисляемые поля или функцию НомерПоПорядку в макете. Для отчётов на СКД это обычно самый чистый вариант, так как нумерация выполняется на этапе формирования, а не выборки данных.
Сравнение вариантов
Быстро и без кода, но нумерация не привязана к УПОРЯДОЧИТЬ ПО и не сбрасывается по группам
Полный контроль порядка и групп, подходит для печатных форм и обработок
Удобно, когда результат передаётся дальше как ТЗ; требует дополнительного прохода по данным
Лучший вариант для отчётов: номер формируется при выводе, запрос не усложняется
Функция АВТОНОМЕРЗАПИСИ в тексте запроса
Встроенная функция АВТОНОМЕРЗАПИСИ() возвращает целое число — порядковый номер записи в результате запроса. Она указывается в списке полей выборки и не принимает аргументов. Это самый быстрый способ добавить номер строки, не выходя из конструктора запроса.
// Пример: нумерация списка товаров
ВЫБРАТЬ
АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,
Номенклатура.Ссылка КАК Товар,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ПометкаУдаления
Ключевое ограничение: функция нумерует записи в том порядке, в котором их фактически сформировал запрос, а не в порядке, заданном предложением УПОРЯДОЧИТЬ ПО. Если добавить сортировку по наименованию, номера могут распределиться не по возрастанию относительно отсортированного списка. Поэтому АВТОНОМЕРЗАПИСИ подходит, когда важен сам факт уникального номера, а не его соответствие визуальному порядку.
Ещё одно ограничение — функция не умеет нумеровать записи отдельно внутри групп. Если нужна нумерация «1, 2, 3» в каждом документе или в каждой категории, АВТОНОМЕРЗАПИСИ не поможет: потребуется обход выборки с иерархией или группировкой и программный счётчик.
Нумерация при обходе выборки в коде
Самый управляемый способ — объявить переменную-счётчик и увеличивать её в цикле обхода выборки. Порядок нумерации в этом случае полностью совпадает с порядком обхода, то есть с сортировкой запроса. Такой подход стандартен для печатных форм, где номер строки выводится в табличную часть документа.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|
|УПОРЯДОЧИТЬ ПО
| Товары.НомерСтроки";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
НомерСтроки = 0;
Пока Выборка.Следующий() Цикл
НомерСтроки = НомерСтроки + 1;
// Вывод НомерСтроки и данных в табличный документ
КонецЦикла;
Для нумерации внутри групп используют обход выборки с типом «ПоГруппировкам»: сначала обходятся группы, затем детальные записи внутри каждой, и счётчик сбрасывается при переходе к новой группе. Это решает задачу, недоступную для АВТОНОМЕРЗАПИСИ.
- 1Сформируйте запрос с нужной сортировкой через УПОРЯДОЧИТЬ ПО
- 2Выполните запрос и получите выборку методом Выбрать()
- 3Объявите переменную-счётчик перед циклом
- 4Увеличивайте счётчик на единицу в начале каждой итерации
- 5Используйте значение счётчика при выводе строки
- 6Для нумерации по группам сбрасывайте счётчик при смене группы
Добавление колонки с номером в таблицу значений
Если результат запроса выгружается в таблицу значений и дальше передаётся в другую процедуру, на форму или в обмен данными, удобно добавить колонку «НомерСтроки» и заполнить её в цикле. Это делает номер частью структуры данных, а не временной переменной.
ТаблицаРезультат = Запрос.Выполнить().Выгрузить();
ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
Номер = 0;
Для Каждого Строка Из ТаблицаРезультат Цикл
Номер = Номер + 1;
Строка.НомерСтроки = Номер;
КонецЦикла;
Перед заполнением таблицу можно отсортировать методом Сортировать() — тогда номера будут соответствовать нужному порядку. Учтите, что дополнительный проход по таблице требует времени: на очень больших выборках (сотни тысяч строк) это заметно, хотя для типовых прикладных задач накладные расходы невелики.
Нумерация строк в отчётах на СКД
В системе компоновки данных нумеровать строки в самом запросе обычно не нужно. СКД предоставляет собственные механизмы: автополе «НомерПоПорядку» в ресурсах и вычисляемых полях, а также системное поле, доступное при настройке структуры отчёта. Номер формируется на этапе вывода, поэтому он всегда соответствует итоговой сортировке и группировкам отчёта.
Чтобы вывести номер строки, добавьте в настройках отчёта поле «Номер по порядку» из списка доступных системных полей либо создайте вычисляемое поле. Если используется программная компоновка или макет, номер выводится через параметр области с инкрементом в процедуре вывода — по аналогии со счётчиком при обходе выборки.
Преимущество подхода в том, что запрос остаётся простым и быстрым, а нумерация корректно работает при любых пользовательских настройках отбора и сортировки. Это особенно важно для отчётов, которые конечные пользователи настраивают самостоятельно.
Если номер строки нужен только для отображения в отчёте, не добавляйте его в запрос вообще — используйте системное поле СКД. Каждое лишнее вычисление в запросе увеличивает нагрузку на СУБД, а пользовательская сортировка всё равно «сломает» заранее присвоенные номера.
Типичные ошибки и как их проверить
Самая распространённая ошибка — ожидать, что АВТОНОМЕРЗАПИСИ пронумерует записи в порядке сортировки. При добавлении УПОРЯДОЧИТЬ ПО номера «разъезжаются», и разработчик получает строки с номерами вперемешку. Решение — нумеровать при обходе выборки или в СКД.
Вторая ошибка — использовать номер строки как устойчивый идентификатор записи. Номер строки в запросе — это позиция в конкретном результате на конкретный момент; после изменения данных или отбора он изменится. Для идентификации записей используйте ссылку или уникальный идентификатор, а не порядковый номер.
Третья типичная проблема — попытка применить АВТОНОМЕРЗАПИСИ в запросе с итогами или в пакетном запросе и неожиданное поведение в итоговых строках. Проверяйте результат на тестовых данных с группировками, прежде чем использовать запрос в рабочем коде.
Как проверить результат
Номера идут 1, 2, 3... в том порядке, в котором выводятся строки
Номера перемешаны относительно сортировки
В каждой группе нумерация начинается с 1
Нумерация сквозная по всем группам
Запрос выполняется за приемлемое время на рабочем объёме данных
Добавление нумерации заметно замедлило выполнение
FAQ: частые вопросы о нумерации строк в запросе 1С
Можно ли пронумеровать строки внутри каждой группы одним запросом?
Штатной функции нумерации по группам в языке запросов 1С нет. Практические варианты: обход выборки с группировками и сброс счётчика в коде, либо соединение таблицы с самой собой с подсчётом количества записей «меньше текущей» — но такой приём сильно нагружает СУБД и оправдан только на малых объёмах. В отчётах СКД нумерация по группам решается настройкой структуры без изменения запроса.
Почему после добавления УПОРЯДОЧИТЬ ПО номера АВТОНОМЕРЗАПИСИ перепутались?
Функция присваивает номера в момент формирования результата, до применения сортировки. Порядок нумерации и порядок сортировки не связаны между собой. Если нужен номер, совпадающий с отсортированным порядком, присваивайте его при обходе выборки или в таблице значений после сортировки.
Как вывести номер строки в печатной форме документа?
Объявите переменную-счётчик перед циклом обхода выборки, увеличивайте её на единицу в каждой итерации и подставляйте значение в параметр области макета, например ОбластьСтрока.Параметры.НомерСтроки = НомерСтроки. В макете создайте ячейку с параметром этого имени.
Работает ли АВТОНОМЕРЗАПИСИ в динамических списках?
Нет, в динамических списках эта функция не поддерживается — запрос динамического списка имеет ограничения на используемые конструкции. Для нумерации в списке обычно используют оформление на уровне формы или выводят данные через отчёт на СКД.
Что лучше для больших выборок: нумерация в запросе или в коде?
АВТОНОМЕРЗАПИСИ выполняется на стороне СУБД и обычно не создаёт существенной нагрузки. Программный счётчик при обходе выборки тоже дёшев, так как это простая операция инкремента. Заметные потери возникают только при избыточных подходах — например, при нумерации через самосоединение таблиц или при лишнем проходе по большой таблице значений.
Можно ли начать нумерацию не с единицы?
Да. При программной нумерации просто инициализируйте счётчик нужным стартовым значением. Для АВТОНОМЕРЗАПИСИ в запросе можно добавить смещение арифметически: АВТОНОМЕРЗАПИСИ() + 100, если это допустимо в конкретной конструкции запроса.
Что важно запомнить
Для простой нумерации в запросе используйте АВТОНОМЕРЗАПИСИ(), но помните: она не связана с сортировкой и не работает по группам. Для точного порядка нумеруйте при обходе выборки или в таблице значений, а для отчётов — средствами СКД. Не используйте номер строки как постоянный идентификатор записи.