Как правильно сгруппировать и отсортировать данные с числовыми префиксами в запросе 1С

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

В процессе разработки отчетов в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда данные в итоговой таблице выстраиваются в странном порядке. Особенно это заметно, когда мы работаем со справочниками, где наименования начинаются с цифр, например, СтатьиЗатрат. Часто можно увидеть порядок типа "1", "10", "2", что совершенно не устраивает конечного пользователя. Разберем детально, почему так происходит и как добиться правильного результата.

Различие между группировкой и сортировкой

Прежде всего, проанализируем важный методологический момент, на котором часто спотыкаются начинающие разработчики. В языке запросов 1С существуют два различных оператора: СГРУППИРОВАТЬ ПО и УПОРЯДОЧИТЬ ПО.

Группировка (СГРУППИРОВАТЬ ПО) используется для «схлопывания» одинаковых записей и применения к ним агрегатных функций (сумма, количество, максимум). Хотя платформа 1С часто выводит сгруппированные записи в определенном порядке, это не является гарантированным поведением. Группировка не предназначена для управления порядком строк.

Сортировка (УПОРЯДОЧИТЬ ПО) — это именно тот инструмент, который отвечает за то, в какой последовательности записи будут представлены в результате запроса. Если нам нужно, чтобы «02. Статья» шла раньше, чем «74. Статья», мы должны использовать именно этот оператор.

Проблема лексикографической сортировки строк

Выясним причину, по которой числа в строках сортируются «неправильно». В программировании стандартная сортировка строк называется лексикографической. Система сравнивает строки посимвольно слева направо. Рассмотрим пример:

  1. Строка "10. Затраты"
  2. Строка "2. Затраты"

Система сравнивает первый символ: "1" меньше, чем "2". Следовательно, строка "10. Затраты" будет стоять выше, чем "2. Затраты", несмотря на то, что число 10 больше 2. Это фундаментальное свойство строковых данных. Чтобы победить это поведение, нам нужно либо привести строки к единому формату (добавить лидирующие нули), либо извлечь числовую часть для сравнения.

Решение 1: Использование правильного поля для сортировки

Проанализируем самый простой вариант. Если в запросе вы используете ссылку на объект (например, СтатьяЗатрат), то при группировке или сортировке система может использовать внутренний идентификатор (UUID), что даст хаотичный порядок. Чтобы данные выстроились по алфавиту (с учетом строковой логики), необходимо обращаться к наименованию. Рассмотрим пример кода:


ВЫБРАТЬ
    Продажи.СтатьяЗатрат КАК Статья,
    СУММА(Продажи.Сумма) КАК Сумма
ИЗ
    РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
    Продажи.СтатьяЗатрат
УПОРЯДОЧИТЬ ПО
    Продажи.СтатьяЗатрат.Наименование

Этот способ решит проблему, если все ваши номера имеют одинаковую длину (например, "01", "02", "10").

Решение 2: Сложная сортировка внутри запроса через ВЫБОР

Если нам всё же необходимо реализовать подобие «естественной сортировки» (Natural Sort) прямо в запросе, не меняя данные в базе, мы можем прибегнуть к созданию искусственных полей сортировки. Рассмотрим ситуацию, когда нам нужно отсортировать строки по первым двум символам, преобразуя их в логические веса.

Посмотрим на пример реализации с использованием временных таблиц:


ВЫБРАТЬ
    Данные.Статья КАК Статья,
    // Извлекаем первый символ и присваиваем вес
    ВЫБОР
        КОГДА ПОДСТРОКА(Данные.Статья.Наименование, 1, 1) = "0" ТОГДА 0
        КОГДА ПОДСТРОКА(Данные.Статья.Наименование, 1, 1) = "1" ТОГДА 1
        // ... и так далее для всех цифр
        ИНАЧЕ 9
    КОНЕЦ КАК ВесПервогоСимвола,
    // Извлекаем второй символ
    ВЫБОР
        КОГДА ПОДСТРОКА(Данные.Статья.Наименование, 2, 1) = "1" ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ВесВторогоСимвола
ПОМЕСТИТЬ ВТ_Сортировка
ИЗ
    Справочник.СтатьиЗатрат КАК Данные;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Статья
ИЗ
    ВТ_Сортировка КАК ВТ
УПОРЯДОЧИТЬ ПО
    ВТ.ВесПервогоСимвола,
    ВТ.ВесВторогоСимвола,
    ВТ.Статья.Наименование

Важно: Этот метод громоздкий и значительно замедляет выполнение запроса на больших объемах данных, так как функции ПОДСТРОКА и ВЫБОР мешают оптимизатору СУБД использовать индексы.

Решение 3: Архитектурно правильный подход (Дополнительный реквизит)

Если вы постоянно сталкиваетесь с необходимостью особой сортировки, проанализируем самый эффективный метод. В справочник СтатьиЗатрат следует добавить числовой реквизит Порядок или КодСортировки.

В этом случае задача решается максимально элегантно:

  1. Пользователь или администратор заполняет числовое поле (например, 1, 2, 10, 20).
  2. В запросе мы просто указываем УПОРЯДОЧИТЬ ПО СтатьяЗатрат.Порядок.

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

Решение 4: Постобработка результата в коде 1С

Если запрос менять нельзя или он слишком сложный, мы можем обработать результат уже после выполнения запроса. Рассмотрим пример с использованием ТаблицыЗначений. Мы можем добавить в таблицу вспомогательную колонку, заполнить её числами, извлеченными из строк, и отсортировать таблицу штатными средствами встроенного языка.


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

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

Для Каждого Строка Из ТаблицаРезультат Цикл
    // Простая логика извлечения первых двух цифр из наименования "07. Статья..."
    Строка.ЧисловойПорядок = Число(Лев(Строка.СтатьяНаименование, 2));
КонецЦикла;

// Сортируем таблицу по новой колонке
ТаблицаРезультат.Сортировать("ЧисловойПорядок Возр");

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

Итоги и рекомендации

Проанализировав ситуацию, можно сделать следующие выводы:

  1. Всегда разделяйте понятия группировки и сортировки. Используйте УПОРЯДОЧИТЬ ПО для управления последовательностью.
  2. Помните, что строки сравниваются посимвольно. "10" всегда будет меньше "2" в строковом представлении.
  3. Для простых задач используйте лидирующие нули в наименованиях (например, "01", "02").
  4. Для сложных профессиональных решений внедряйте дополнительные числовые реквизиты порядка в справочники.
  5. Если нужно "быстро и костыльно" — используйте обработку результата запроса в ТаблицеЗначений перед выводом в макет.

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

← На главную