Сортировка данных в 1С 8.3 для разработчика: где задавать порядок

· 9 мин

Содержание

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

Ниже все основные способы для платформы 8.3: от запроса до динамического списка, с рабочими примерами и разбором ошибок, из-за которых «порядок не работает ».

Откуда брать порядок: какой способ выбрать

Правило простое: сортируйте как можно ближе к источнику. Сервер СУБД упорядочит выборку быстрее, чем вы переберёте её в цикле.

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

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

Сортировка в запросе: УПОРЯДОЧИТЬ ПО и АВТОУПОРЯДОЧИВАНИЕ

Оператор стоит в конце запроса (перед ИТОГИ, если они есть) и перечисляет поля через запятую. Направление: ВОЗР (по умолчанию) или УБЫВ.

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Номенклатура.Наименование КАК Наименование,
|	Номенклатура.Код КАК Код
|ИЗ
|	Справочник.Номенклатура КАК Номенклатура
|
|УПОРЯДОЧИТЬ ПО
|	Наименование,
|	Код УБЫВ";
Выборка = Запрос.Выполнить().Выбрать();

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

Сортировка по ссылке и по реквизиту

Если в УПОРЯДОЧИТЬ ПО указать поле ссылочного типа, порядок определяется по основному представлению объекта: у справочника это обычно наименование, у документа — дата и номер. Поэтому записи расходятся «по алфавиту», а не по внутреннему идентификатору.

Нужен другой порядок — берите реквизит явно:

|УПОРЯДОЧИТЬ ПО
|	Документ.Дата УБЫВ,
|	Документ.Номер

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

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

Первые N записей

Для рейтингов и «последних документов» сочетают ПЕРВЫЕ и сортировку:

ВЫБРАТЬ ПЕРВЫЕ 10
	Продажи.Ссылка КАК Ссылка,
	Продажи.Дата КАК Дата
ИЗ
	Документ.РеализацияТоваровУслуг КАК Продажи
УПОРЯДОЧИТЬ ПО
	Дата УБЫВ

Без УПОРЯДОЧИТЬ ПО слово ПЕРВЫЕ вернёт произвольные десять записей, а не самые свежие.

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

Сортировка в коде: таблица значений, список, массив

Таблица значений

Метод Сортировать принимает строку с колонками. После имени колонки через пробел можно указать Возр или Убыв.

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Контрагент");
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

// ... заполнение ...

Таблица.Сортировать("Сумма Убыв, Контрагент");

Второй параметр метода — объект сравнения СравнениеЗначений. Он нужен, когда колонка содержит значения разных типов.

Если нужен только ранжированный список без изменения самой таблицы, скопируйте её через Скопировать() и сортируйте копию.

Список значений

У СписокЗначений два метода:

  • СортироватьПоЗначению(Направление) — по самому значению;
  • СортироватьПоПредставлению(Направление) — по тексту, который видит пользователь.
Список = Новый СписокЗначений;
Список.Добавить("Яблоки");
Список.Добавить("Абрикосы");
Список.Добавить("Груши");
Список.СортироватьПоПредставлению(НаправлениеСортировки.Возр);

Массив

Готового метода у массива нет. Типичный приём — загрузить значения в список значений, отсортировать и выгрузить обратно:

Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(МойМассив);
Список.СортироватьПоЗначению(НаправлениеСортировки.Возр);
МойМассив = Список.ВыгрузитьЗначения();

Для массива чисел или строк это самый короткий вариант. Если в массиве структуры, сортируйте таблицу значений по нужному полю.

Порядок «как у человека»

Строки сортируются посимвольно: «10» окажется раньше «2». Если колонка хранит номера как строки, либо переведите их в число, либо дополните нулями слева до одинаковой длины. Для документов с номерами вида 00000012 проблемы нет, а вот для кодов «А-2» и «А-10» она есть.

Порядок в СКД: закладка «Порядок» и программное добавление

В схеме компоновки данных сортировка живёт в настройках варианта отчёта. Открываете схему в конфигураторе, закладка «Настройки», затем «Порядок». Перетаскиваете туда поля и для каждого выбираете направление.

Порядок можно задать:

  1. в настройках по умолчанию — все пользователи увидят его сразу;
  2. в пользовательских настройках — пользователь меняет его в отчёте сам;
  3. для отдельной группировки — тогда сортируются только строки внутри неё.

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

Добавление сортировки программно

Если отчёт строится кодом, элемент порядка добавляют в коллекцию Порядок настроек:

Порядок = КомпоновщикНастроек.Настройки.Порядок;
Элемент = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
Элемент.Поле = Новый ПолеКомпоновкиДанных("Сумма");
Элемент.ТипУпорядочивания = НаправлениеУпорядочиванияКомпоновкиДанных.Убывание;
Элемент.Использование = Истина;

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

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

Сортировка итогов

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

Динамический список формы: порядок по умолчанию и из кода

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

Из кода порядок меняют на сервере в обработчике, например ПриСозданииНаСервере:

Список.Порядок.Элементы.Очистить();
Элемент = Список.Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
Элемент.Поле = Новый ПолеКомпоновкиДанных("Дата");
Элемент.ТипУпорядочивания = НаправлениеУпорядочиванияКомпоновкиДанных.Убывание;
Элемент.Использование = Истина;

Здесь Список — имя реквизита формы. Если у вас реквизит называется иначе, подставьте своё имя.

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

Особые случаи: объединения, итоги, дерево, свой порядок

ОБЪЕДИНИТЬ ВСЕ и временные таблицы

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

Во временной таблице порядок строк сам по себе ничего не значит. Сортируйте в том запросе, который отдаёт данные потребителю, а не в промежуточном. Исключение — ПЕРВЫЕ N: там сортировка нужна уже при создании таблицы, иначе в неё попадут случайные записи.

Запрос с ИТОГАМИ

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

Дерево значений

У строк дерева значений есть собственный метод Сортировать. Вторым параметром он принимает признак рекурсивной сортировки. Если передать Истина, упорядочатся и подчинённые строки на всех уровнях, иначе только верхний.

Дерево.Строки.Сортировать("Наименование", Истина);

Сортировка действует внутри каждого родителя. Строки одного уровня не «переезжают» к другому родителю.

Свой порядок, не алфавитный

Нужно вывести статусы в порядке «Новый, В работе, Закрыт», а не по алфавиту? Сравнение по тексту не поможет. Два рабочих варианта.

  1. Если статус — перечисление, порядок значений задан в конфигураторе, и сортировка по полю перечисления идёт именно по нему, а не по тексту. Менять порядок значений можно на закладке со значениями перечисления.
  2. Если статус хранится строкой, добавьте в запрос вычисляемое поле-ключ:
ВЫБРАТЬ
	Заявки.Номер КАК Номер,
	Заявки.Статус КАК Статус,
	ВЫБОР
		КОГДА Заявки.Статус = "Новый" ТОГДА 1
		КОГДА Заявки.Статус = "В работе" ТОГДА 2
		ИНАЧЕ 3
	КОНЕЦ КАК Ключ
ИЗ
	Справочник.Заявки КАК Заявки
УПОРЯДОЧИТЬ ПО
	Ключ,
	Номер

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

Устойчивая сортировка и «последняя запись»

Если строки одинаковы по ключу сортировки, их взаимный порядок не определён. Для задач вроде «взять последний документ за день» всегда добавляйте второй ключ, который различает записи: номер, дату с временем или ссылку. Тогда результат повторяется от запуска к запуску.

Скорость: индексы и объём выборки

Сортировка без индекса заставляет СУБД собрать весь результат и упорядочить его целиком. На таблице в сотни тысяч записей это заметно.

Что реально помогает:

  • 🔹 включите у реквизита «Индексировать» (или «Индексировать с дополнительным упорядочиванием»), если по нему часто фильтруют и сортируют;
  • 🔹 ограничивайте выборку: условие ГДЕ и ПЕРВЫЕ N до сортировки, а не после;
  • 🔹 не сортируйте по вычисляемым выражениям там, где можно отсортировать по готовому полю;
  • 🔹 для регистров сведений и накопления используйте порядок измерений, он совпадает с порядком индекса.

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

Изменение индексирования реквизита запускает реструктуризацию таблицы базы. На большой базе это занимает время и требует монопольного доступа. Делайте это в нерабочее время и сначала на копии.

Консоль запросов и свои обработки

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

В собственной обработке с выводом в табличный документ самый частый подход такой:

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

Если пользователь должен менять порядок на экране, проще построить форму на динамическом списке или СКД, чем писать свою сортировку по щелчку.

Типичные ошибки

СимптомВероятная причинаЧто делать
Порядок «плавает» между запускамиНет УПОРЯДОЧИТЬ ПОДобавьте явную сортировку
«10» раньше «2»Числа хранятся в строкеПриведите к числу или дополните нулями
Сортировка по ссылке идёт «не по дате»Порядок по представлению ссылкиУкажите Ссылка.Дата
В СКД порядок из запроса не виденНастройки переопределяют запросЗадайте порядок в настройках
Метод Сортировать выдаёт ошибкуНет такой колонки или опечатка в имениПроверьте имена колонок
Пустые значения оказались наверхуПустые значения считаются наименьшимиОтфильтруйте их или обработайте отдельно

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

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

Как отсортировать массив в 1С?
У массива нет метода сортировки. Загрузите его в список значений через ЗагрузитьЗначения, вызовите СортироватьПоЗначению и выгрузите обратно методом ВыгрузитьЗначения.
Можно ли сортировать по нескольким полям сразу?
Да. В запросе перечислите поля через запятую после УПОРЯДОЧИТЬ ПО, в таблице значений — через запятую в строке метода Сортировать. Первое поле главное.
Как задать обратный порядок?
В запросе добавьте УБЫВ после поля. В таблице значений — слово Убыв после имени колонки. В списке значений передайте НаправлениеСортировки.Убыв.
Почему в отчёте на СКД сортировка из запроса не действует?
Порядок, заданный в настройках, имеет приоритет. Откройте закладку «Порядок» настроек варианта и добавьте нужные поля туда.
Нужно ли ставить индекс на каждое поле, по которому сортируем?
Нет. Индекс ускоряет чтение, но замедляет запись и увеличивает базу. Ставьте его на реквизиты, по которым часто идёт отбор или сортировка в больших таблицах.