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

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

Как упорядочить временную таблицу в 1С

Как упорядочить временную таблицу в 1С: УПОРЯДОЧИТЬ ПО в запросе, сортировка таблицы значений методом Сортировать, типичные ошибки и примеры кода.

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

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

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

Как устроены временные таблицы и почему порядок не гарантирован

Временная таблица в 1С — это материализованный промежуточный результат запроса, который живёт в рамках менеджера временных таблиц и доступен последующим запросам пакета. Физически она хранится на сервере СУБД (или в памяти для файлового варианта) как набор строк без какого-либо индекса по умолчанию.

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

Практический вывод: любая логика, зависящая от порядка строк (нумерация, накопительные итоги, группировка в обходе выборки), должна опираться на явную сортировку в финальном запросе. Полагаться на «как обычно выходит» нельзя — после изменения запроса, обновления платформы или роста объёма данных порядок может измениться.

Упорядочивание при выборке из временной таблицы

Основной и рекомендуемый способ — добавить предложение УПОРЯДОЧИТЬ ПО в запрос, который читает временную таблицу. Сортировать можно по любым полям выборки, в том числе по полям, полученным через соединение с другими таблицами.

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

Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

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

"ВЫБРАТЬ

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

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

|ИЗ

| ВТ_Товары КАК Товары

|

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

| Количество УБЫВ,

| Номенклатура";

Ключевые слова ВОЗР и УБЫВ задают направление сортировки; по умолчанию используется возрастание. Если полей несколько, они перечисляются через запятую — сначала сортировка по первому полю, внутри одинаковых значений — по второму и так далее.

Дополнительно доступна конструкция АВТОУПОРЯДОЧИВАНИЕ. Она сортирует результат по ссылкам и представлениям ссылочных полей, если явное упорядочивание не задано. Полагаться на неё стоит только в простых случаях: для прикладной логики явное УПОРЯДОЧИТЬ ПО читаемее и предсказуемее.

Почему нельзя сортировать внутри запроса с ПОМЕСТИТЬ

Частая ошибка начинающих разработчиков — попытка написать УПОРЯДОЧИТЬ ПО в том же запросе, где данные помещаются во временную таблицу. Синтаксически конструктор запросов такую комбинацию не предлагает, а если сформировать текст вручную, платформа либо выдаст ошибку, либо проигнорирует сортировку.

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

Если порядок нужен не для вывода, а для последующей обработки внутри пакета запросов (например, соединение «с предыдущей строкой»), стандартной сортировки недостаточно. Такие задачи решаются через нумерацию строк на стороне СУБД или через выгрузку в таблицу значений с последующим обходом.

Сортировка после выгрузки в таблицу значений

Когда результат запроса выгружается методом Выгрузить(), получается таблица значений — полноценный объект в памяти с собственными средствами сортировки. Метод Сортировать() принимает строку со списком колонок и направлений.

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

ТЗ.Сортировать("Количество Убыв, Номенклатура Возр");

Направления задаются словами Возр и Убыв через пробел после имени колонки; колонки перечисляются через запятую. Если направление не указать, применяется сортировка по возрастанию. Метод выполняется в памяти, поэтому для очень больших таблиц выгоднее сортировать на стороне СУБД в запросе — там работают оптимизатор и индексы.

Для дерева значений есть аналогичные механизмы: сортировка строк конкретного уровня выполняется через коллекцию строк (Строки.Сортировать(...)). Это удобно при выводе иерархических данных в табличное поле или отчёт.

Где сортировать

УПОРЯДОЧИТЬ ПО в запросе

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

ТЗ.Сортировать() после выгрузки

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

АВТОУПОРЯДОЧИВАНИЕ

Подходит для простых списков ссылок без требований к точному порядку. Не заменяет явную сортировку в прикладной логике.

Индексация временных таблиц и её связь с сортировкой

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

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

Пошаговый порядок действий

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

Порядок действий
  1. 1
    Создайте менеджер временных таблиц и назначьте его всем запросам пакета
  2. 2
    Сформируйте временную таблицу запросом с ПОМЕСТИТЬ (без сортировки в нём)
  3. 3
    При необходимости добавьте ИНДЕКСИРОВАТЬ ПО по полям соединений
  4. 4
    Напишите финальный запрос: ВЫБРАТЬ ... ИЗ ВТ_Имя ... УПОРЯДОЧИТЬ ПО полям
  5. 5
    Выполните запрос и обойдите выборку или выгрузите результат
  6. 6
    Если данные уже в таблице значений — примените ТЗ.Сортировать() с нужными колонками
  7. 7
    После завершения работы уничтожьте временные таблицы или закройте менеджер

После завершения работы временные таблицы желательно уничтожать явно (запросом УНИЧТОЖИТЬ или закрытием менеджера), особенно если пакет выполняется в длительной операции. Это освобождает ресурсы СУБД и снижает риск конфликтов имён при повторном использовании менеджера.

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

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

Отдельная группа проблем — сортировка полей составного типа или полей, содержащих NULL. Значения NULL при сортировке по возрастанию обычно идут первыми; если это нарушает логику отчёта, используйте ЕСТЬNULL для замены на осмысленное значение или фильтруйте такие строки заранее.

Контрольные точки

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

Порядок строк в выборке
Норма

Строки идут строго по указанным полям и направлениям, повторный запуск даёт тот же порядок

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

Порядок меняется между выполнениями или не соответствует УПОРЯДОЧИТЬ ПО — значит, сортировка задана не в финальном запросе

Сортировка числовых данных
Норма

Числа упорядочены по значению (2, 10, 100)

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

Порядок «1, 10, 2» — поле строковое, нужна сортировка по числовому представлению

Работа с NULL
Норма

Пустые значения обработаны через ЕСТЬNULL и стоят в ожидаемом месте

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

Строки с NULL попадают в начало и нарушают логику обхода

Для отладки удобно временно выгрузить результат в таблицу значений и просмотреть её в отладчике или вывести через консоль запросов. Проверяйте не только первый десяток строк — проблемы сортировки часто проявляются на границах групп и на больших объёмах.

Итог

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

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

Частые вопросы

Можно ли отсортировать саму временную таблицу, чтобы она хранилась упорядоченной?

Нет. Временная таблица — неупорядоченный набор строк, и платформа не предоставляет способа зафиксировать порядок хранения. Упорядочивание применяется только при чтении: добавьте УПОРЯДОЧИТЬ ПО в каждый запрос, которому важен порядок строк.

Чем АВТОУПОРЯДОЧИВАНИЕ отличается от УПОРЯДОЧИТЬ ПО?

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

Как отсортировать по полю, которого нет в выборке?

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

Почему числа сортируются как «1, 10, 2, 25»?

Поле имеет строковый тип, и сортировка выполняется посимвольно. Решения: привести значение к числу в запросе, сортировать по исходному числовому полю или дополнить строки лидирующими нулями до фиксированной длины.

Что быстрее — сортировка в запросе или методом Сортировать()?

На больших объёмах сортировка в запросе обычно эффективнее: она выполняется на СУБД без передачи всех данных в память приложения. Метод Сортировать() оправдан, когда таблица значений уже нужна в коде для дальнейшей обработки.

Нужно ли уничтожать временные таблицы после использования?

Желательно, особенно в длительных операциях и при больших объёмах. Используйте запрос УНИЧТОЖИТЬ ИмяТаблицы или закройте менеджер временных таблиц — это освобождает ресурсы СУБД и предотвращает конфликты имён при повторном выполнении пакета.