Как в запросе 1С 7.7 выполнить упорядочивание по сумме в порядке убывания?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

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

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

Способ 1. Использование штатного механизма запроса и метода Группировка()

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

Шаг 1. Подготовка текста запроса. Чтобы система вообще начала подготавливать данные для сортировки по значению функции (например, по сумме), необходимо явно указать это в тексте запроса. Если этого не сделать, никакие дальнейшие манипуляции в коде не помогут.

Рассмотрим правильный фрагмент текста запроса (для предварительной отладки может пригодиться читалка регистров):


ТекстЗапроса = "
|Период с ВыбНачПериода по ВыбКонПериода;
|Покупатель = Регистр.Продажи.Покупатель;
|Сумма1 = Регистр.Продажи.ПродСтоимость;
|Функция СуммаИтог = Сумма(Сумма1);
|Группировка Покупатель без групп Упорядочить по СуммаИтог;";

Шаг 2. Обход результатов с параметром направления. Теперь самое важное. Метод Группировка(), который мы используем в цикле Пока, принимает два основных параметра. Рассмотрим их подробнее:

  1. Номер или имя группировки: указывает, к какому уровню вложенности мы обращаемся.
  2. Направление сортировки: именно здесь мы задаем порядок. Значение 1 означает возрастание (по умолчанию), а значение -1 — убывание.

Посмотрим на финальный программный код, который решает задачу:


Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
КонецЕсли;

// Здесь мы указываем -1 для сортировки по убыванию
Пока Запрос.Группировка(1, -1) = 1 Цикл
    // В этом цикле Покупатели будут выходить от большего к меньшему по СуммаИтог
    Сообщить("Покупатель: " + Запрос.Покупатель + " - Сумма: " + Запрос.СуммаИтог);
КонецЦикла;

Важное замечание: Если в тексте запроса вы забудете написать Упорядочить по СуммаИтог, то вызов Запрос.Группировка(1, -1) проигнорирует минус единицу и выведет данные в стандартном порядке (обычно по наименованию или внутреннему ID объекта).

Способ 2. Выгрузка в Таблицу Значений (ТЗ)

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

В этом случае наиболее эффективным методом будет выгрузка результата запроса в объект ТаблицаЗначений (здесь может пригодиться универсальный отчет по таблице значений). Рассмотрим этот алгоритм по шагам:

  1. Выполняем запрос без обязательного использования Упорядочить по (хотя его можно оставить для предварительной обработки).
  2. Выгружаем результаты в ТЗ с помощью метода Выгрузить().
  3. Используем мощный метод Сортировать() объекта ТЗ.

Пример реализации данного подхода (также полезна настраиваемая распечатка таблицы значений):


ТЗ = СоздатьОбъект("ТаблицаЗначений");
// Выгружаем результаты запроса в таблицу
// Второй параметр 1 означает, что мы выгружаем группировки
Запрос.Выгрузить(ТЗ, 1, 0);

// Сортируем таблицу. 
// Знак "-" после названия колонки означает убывание.
// Если знака нет или стоит "+", то сортировка идет по возрастанию.
ТЗ.Сортировать("СуммаИтог-, Покупатель+");

// Теперь обходим готовую таблицу
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    // Выводим данные в печатную форму или отчет
    // Доступ к данным осуществляется через колонки ТЗ
КонецЦикла;

Преимущества этого способа:

Способ 3. Прямые SQL-запросы (внешняя компонента 1C++)

Выясним причину, по которой опытные разработчики часто отказываются от штатных запросов 1С 7.7. На больших объемах данных (базы размером в десятки гигабайт) штатный движок запросов начинает работать крайне медленно. Это происходит потому, что 1С сначала копирует данные во временные файлы DBF, производит расчеты и только потом сортирует.

Если ваша база работает на Microsoft SQL Server, вы можете использовать внешнюю компоненту 1C++ для написания «прямых» запросов. Рассмотрим, как выглядит решение нашей задачи на языке SQL:


// Пример упрощенного SQL-запроса через 1С++
ТекстЗапроса = "
|SELECT
|    $Рег.Покупатель as [Покупатель $Справочник.Клиенты],
|    SUM($Рег.ПродСтоимость) as СуммаИтог
|FROM
|    $Регистр.Продажи as Рег
|WHERE
|    Рег.PERIOD BETWEEN :НачДата AND :КонДата
|GROUP BY
|    $Рег.Покупатель
|ORDER BY
|    СуммаИтог DESC
|";

В данном случае ключевое слово DESC (descending) в конструкции ORDER BY отвечает за сортировку по убыванию на уровне самого SQL-сервера. Это решение работает в десятки, а иногда и в сотни раз быстрее штатных средств, так как сервер БД оптимизирует выполнение задачи на уровне своих внутренних алгоритмов.

Сравнение методов и рекомендации

Подведем итог и выясним, какой метод выбрать в зависимости от условий:

  1. Метод Группировка(1, -1) — лучше всего подходит для простых отчетов в небольших и средних базах, где не требуется сложная логика и важна читаемость кода.
  2. Выгрузка в ТЗ — идеальный вариант для создания сложных интерактивных отчетов, где пользователю может потребоваться пересортировка данных «на лету» или где нужна сложная многоуровневая сортировка.
  3. Прямые запросы (SQL) — незаменимы в высоконагруженных системах и крупных корпоративных базах данных, где скорость формирования отчета является критическим показателем.

Проанализировав все способы, мы видим, что 1С 7.7 предоставляет достаточно инструментов для решения задачи упорядочивания. Главное — помнить о необходимости синхронизации текста запроса и параметров метода обхода группировок.

← На главную