Сортировка по нужному полю в запросе 1С: где добавить и как не потерять скорость

· 10 мин

Содержание

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

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

Добавляем поле сортировки через конструктор запросов

Откройте запрос в модуле или в наборе данных СКД и нажмите Конструктор запроса. Если запрос уже написан вручную, конструктор попытается разобрать его. Сложные тексты он порой не принимает целиком — тогда правьте текст руками, см. следующий раздел.

Порядок действий:

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

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

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

Ручное редактирование: синтаксис УПОРЯДОЧИТЬ ПО

Фраза стоит в конце запроса. Если есть ИТОГИ, порядок указывается перед ними:

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

Что здесь важно:

  • 🔹 Направление — слова ВОЗР (по умолчанию) и УБЫВ. Они относятся к одному полю, а не ко всей фразе: у каждого поля своё направление.
  • 🔹 Поля перечисляют через запятую, приоритет — слева направо.
  • 🔹 Можно указать псевдоним из списка выбора (Дата), а можно полный путь (РеализацияТоваровУслуг.Дата).
  • 🔹 Сортировать можно по реквизитам, которых нет в выборке, но тогда используйте полный путь через точку.

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

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

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

Первый способ точнее: вы сами выбираете, по чему сортировать. Второй короче, но порядок зависит от настроек объекта метаданных.

Первые N записей и объединения

Связка ВЫБРАТЬ ПЕРВЫЕ 10 без УПОРЯДОЧИТЬ ПО возвращает «какие-то» десять строк. Для «десяти последних документов» порядок обязателен: УПОРЯДОЧИТЬ ПО Дата УБЫВ.

При ОБЪЕДИНИТЬ ВСЕ сортировка пишется один раз — в самом конце, после последнего запроса пакета объединения, и действует на результат целиком. Имена полей берутся из первого запроса объединения. Если назвать поле в порядке именем из второго запроса, получите ошибку «поле не найдено».

Сложная логика: временные таблицы и порядок

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

Правило простое: сортируйте в последнем запросе пакета, который отдаёт результат.

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

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

Пакет выполняется подряд, запрос с ПОМЕСТИТЬ результата не отдаёт. Если после Запрос.ВыполнитьПакет() нужна выборка, берите результат нужного запроса по индексу (счёт идёт с нуля): в примере выше это Результат[1].Выбрать(). Если же вызвать Запрос.Выполнить(), вернётся результат последнего запроса пакета.

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

Бывает, что сортировку нужно «закрепить» в промежуточных данных — например, чтобы взять по каждому контрагенту последнюю запись. Для этого используют не сортировку, а функции получения последней записи или соединение с агрегатом МАКСИМУМ(Период). Порядок строк во временной таблице — не механизм хранения порядка.

Сортировка в СКД: настройки, схема и код

В отчётах на СКД запрос — лишь поставщик данных. Итоговый порядок строк определяют настройки компоновки.

Через конструктор схемы

  1. Откройте схему компоновки данных отчёта.
  2. Перейдите на вкладку Настройки.
  3. В дереве структуры выберите нужную группировку (или корневой элемент Отчёт).
  4. Внизу переключитесь на вкладку Порядок.
  5. Добавьте поле и выберите направление.

Если у группировки нет собственного порядка, он берётся с вышестоящего уровня. Это удобно: один раз задали порядок на корне, и он действует на все вложенные группировки.

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

Через код

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

Порядок = КомпоновщикНастроек.Настройки.Порядок;
Порядок.Элементы.Очистить();

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

Это порядок на корневом уровне. Для порядка внутри группировки обращайтесь к Настройки.Структура[0].Порядок.

Сортировка по нескольким полям

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

Таблица значений и динамический список в форме

Если данные уже получены и лежат в таблице значений, запрос не нужен. Для этого есть метод Сортировать:

ТаблицаЗначений.Сортировать("Дата Убыв, Номер");

Столбцы перечисляют через запятую, направление пишут после имени. Сортируется сама таблица, а не копия. Для списка значений есть СортироватьПоЗначению() и СортироватьПоПредставлению().

Запомните один нюанс: сортировка таблицы по столбцу со ссылками работает по тем же правилам, что и в запросе — не по тексту наименования. Чтобы упорядочить по наименованию, заведите в таблице отдельный столбец с этим текстом и сортируйте по нему.

Скорость: что делает сортировка с производительностью

Сортировка — дорогая операция, особенно на больших выборках. Что помогает:

ПриёмКогда применятьЧто получаете
Ограничение через ПЕРВЫЕ NНужны последние или самые крупные записиСерверу не нужно упорядочивать всю выборку
Фильтр в ГДЕ до сортировкиВсегдаУпорядочивается меньше строк
Индекс реквизитаСортировка идёт по одному и тому же реквизиту каждый деньБыстрее порядок и поиск
Индексирование временной таблицыТаблица большая и соединяется по ключуБыстрее соединения и выборки
Сортировка в клиентеДанных мало, порядок меняет пользовательМеньше запросов к серверу

Индекс реквизита

В конфигураторе откройте свойства реквизита справочника или документа. Свойство Индексировать включает индексирование; вариант с дополнительным упорядочиванием полезен для строковых реквизитов, которые часто используют в порядке. Лишние индексы замедляют запись и увеличивают размер базы, поэтому ставьте их только на те реквизиты, по которым реально сортируют и ищут.

Индексирование временной таблицы

Для временных таблиц есть фраза ИНДЕКСИРОВАТЬ ПО:

ВЫБРАТЬ
    Контрагенты.Ссылка КАК Контрагент,
    Контрагенты.Наименование КАК Наименование
ПОМЕСТИТЬ ВТ_Контрагенты
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ИНДЕКСИРОВАТЬ ПО
    Контрагент

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

Поля неограниченной длины

По реквизиту строки неограниченной длины сортировать нельзя. Приведите значение к ограниченной строке: ВЫРАЗИТЬ(Документ.Комментарий КАК СТРОКА(100)). Помните, что сортировка пойдёт только по первым ста символам.

Порядок в динамическом списке формы

Если нужно, чтобы пользователь сам менял порядок в списке формы, запрос не трогают. Откройте форму в конфигураторе, выделите реквизит с типом Динамический список и в его свойствах нажмите Настройка списка. Дальше путь тот же, что в СКД: вкладка Порядок, добавить поле, выбрать направление.

Отдельный случай — основной порядок списка справочника. Он задаётся в свойствах объекта метаданных: у справочника есть настройки ввода по строке и порядка по умолчанию (код или наименование). Если список открывается не в том порядке, сначала проверьте эти настройки, а уже потом лезьте в запрос.

В программно собранном динамическом списке порядок меняют так:

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

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

Практический пример: отчёт, где порядок не совпадает с ожиданием

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

Что делать:

  1. Откройте схему, вкладку Настройки, выберите группировку Контрагент.
  2. На вкладке Порядок замените поле на Сумма и поставьте убывание.
  3. Если порядок нужен и по умолчанию, и по выбору пользователя, разрешите его изменение: включите для элемента пользовательскую настройку, тогда он появится в окне настроек отчёта.

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

Числа в строках

Отдельная ловушка — номера документов и коды, которые хранятся строкой. При сортировке по возрастанию строка «10» окажется раньше «2», потому что сравниваются символы, а не числа. Если код всегда состоит из цифр, а длина разная, у справочника включают контроль длины и дополнение нулями слева. Для старых данных вариант — приведение в запросе: ВЫРАЗИТЬ(Код КАК Число(15, 0)). Но он сработает, только если во всех строках нет букв, иначе запрос завершится ошибкой преобразования. Сначала проверьте данные отбором.

Регистр букв и пустые значения

Сортировка строк в запросе зависит от настроек сортировки базы данных, а не от того, как вы пишете запрос. Поэтому регистр букв обычно не влияет на порядок, и «а» и «А» идут рядом. Пустые значения при возрастании оказываются вверху. Если пустых нужно показывать в конце, используйте условие в списке полей: добавьте поле ВЫБОР КОГДА Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК ПризнакПустого и сортируйте сначала по нему, потом по основному полю.

Частые ошибки при добавлении сортировки

Ошибки в этой теме повторяются от проекта к проекту:

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

Перед тем как править запрос, по которому строятся регламентные отчёты, сохраните его старый текст. Вернуться к нему проще, чем искать, какая именно фраза изменила порядок.

Если сортировка не работает
Выполнено: 0 / 5

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

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