При формировании отчетов и обработке кадровых или финансовых данных часто возникает задача нумерации строк. Однако задача усложняется, когда в общей выборке документов (например, приемы на работу, увольнения, отпуска) необходимо присвоить сквозные порядковые номера не всем записям подряд, а только документам определенного вида — например, только кадровым перемещениям.
Рассмотрим детально, как можно решить эту задачу двумя основными способами: средствами языка запросов 1С и с помощью обработки результата в коде на встроенном языке.
Проанализируем решение задачи на уровне языка запросов. Поскольку в языке запросов платформы 1С версии 8.2 и ранних версиях 8.3 отсутствуют оконные функции (такие как ROW_NUMBER()), нумерация реализовывалась через левое или внутреннее соединение таблицы с самой собой по условию нестрогого сравнения ссылок или дат.
Чтобы сквозные номера присваивались исключительно документам вида Документ.КадровоеПеремещениеОрганизаций, ограничим условия соединения оператором ССЫЛКА. Рассмотрим пример построения такого запроса:
ВЫБРАТЬ
ТЗ.Ссылка КАК Ссылка,
ТЗ.Дата КАК Дата,
КОЛИЧЕСТВО(ТЗК.Ссылка) КАК НомерПоПорядку
ИЗ
ВТ_Данные КАК ТЗ
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Данные КАК ТЗК
ПО ТЗ.Ссылка >= ТЗК.Ссылка
И ТЗК.Ссылка ССЫЛКА Документ.КадровоеПеремещениеОрганизаций
И ТЗ.Ссылка ССЫЛКА Документ.КадровоеПеремещениеОрганизаций
СГРУППИРОВАТЬ ПО
ТЗ.Ссылка,
ТЗ.Дата
Разберем по шагам, как работает этот алгоритм в запросе:
ТЗ.Ссылка >= ТЗК.Ссылка, что позволяет посчитать количество предшествующих записей.ССЫЛКА Документ.КадровоеПеремещениеОрганизаций накладывается как на левую, так и на правую часть соединения. Благодаря этому в подсчете количества участвуют только документы кадрового перемещения.0 или NULL.Важно: этот способ создает высокую нагрузку при большом количестве записей (сложность $O(N^2)$). Если в выборке присутствуют тысячи регистраторов, выполнение такого соединения может занять длительное время. Поэтому для повышения производительности рекомендуется сначала отбирать нужные документы во временную таблицу и нумеровать только их.
Если нумерация в самом запросе приводит к падению производительности или чрезмерному усложнению текста запроса, вынесем логику простановки номеров на этап обработки результата во встроенном языке 1С. Это наиболее оптимальный по скорости выполнения подход.
Выполним обычный запрос, получающий все необходимые регистраторы без сложных соединений, после чего при обходе выборки организуем счетчик с проверкой типа текущего документа через функцию ТипЗнч():
СчетчикПеремещений = 0;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Проверяем, является ли регистратор кадровым перемещением
Если ТипЗнч(Выборка.Регистратор) = Тип("ДокументСсылка.КадровоеПеремещениеОрганизаций") Тогда
СчетчикПеремещений = СчетчикПеремещений + 1;
НомерДляВывода = СчетчикПеремещений;
Иначе
НомерДляВывода = Неопределено; // или 0
КонецЕсли;
// Дальнейшая обработка или вывод в ТабличныйДокумент
// ВывестиСтроку(Выборка.Регистратор, НомерДляВывода);
КонецЦикла;
Выясним преимущества данного метода:
ТипЗнч() и переменная-счетчик легко отслеживаются в отладчике.Для решения задачи нумерации выбранного типа документов в 1С применяются два основных подхода. Если критично получить готовый порядковый номер непосредственно в самом запросе, используйте соединение таблицы с добавлением условия ССЫЛКА Документ.ИмяДокумента. В случаях, когда важна скорость выполнения на больших объемах данных, предпочтительнее выполнять обычную выборку и увеличивать счетчик в цикле Пока Выборка.Следующий() при условии равенства типа объекта через ТипЗнч().