Сортировка по нужному полю в запросе 1С: где добавить и как не потерять скорость
Содержание
Чаще всего поле сортировки «не добавляется» по одной причине: оно выбрано в списке полей запроса, но нигде не указано в порядке. Список выбранных полей и порядок строк — разные вещи. Сортировка задаётся отдельно: либо на вкладке Порядок конструктора запроса, либо фразой УПОРЯДОЧИТЬ ПО в тексте.
Ниже — все места, где в 1С 8.3 добавляют сортировку: запрос, временные таблицы, система компоновки данных (СКД) и таблица значений. Отдельно разобрано, как порядок влияет на скорость и почему строки иногда «не слушаются».
Добавляем поле сортировки через конструктор запросов
Откройте запрос в модуле или в наборе данных СКД и нажмите Конструктор запроса. Если запрос уже написан вручную, конструктор попытается разобрать его. Сложные тексты он порой не принимает целиком — тогда правьте текст руками, см. следующий раздел.
Порядок действий:
- Перейдите на вкладку
Порядок. - В левой части найдите нужное поле (раскройте таблицу, чтобы увидеть реквизиты и вложенные поля через точку).
- Перетащите поле вправо или дважды щёлкните по нему.
- В колонке направления выберите
ВозрилиУбыв. - Если полей несколько, расставьте их по приоритету: первое сортирует главным, остальные — внутри равных значений.
- Нажмите
ОКи проверьте текст запроса: внизу должна появиться фразаУПОРЯДОЧИТЬ ПО.
Под списком есть флажок Автоупорядочивание. Он нужен, когда в порядке участвуют ссылки. Включение добавляет в текст ключевое слово АВТОУПОРЯДОЧИВАНИЕ, и ссылки на справочники и документы упорядочиваются так, как их показывает система: справочники — по основному представлению (наименованию или коду), документы — по дате и номеру.
Если нужное поле не видно в левой части вкладки Порядок, проверьте вкладку Таблицы и поля. Для запросов с группировкой в порядке доступны только поля группировки и агрегатные функции.
Ручное редактирование: синтаксис УПОРЯДОЧИТЬ ПО
Фраза стоит в конце запроса. Если есть ИТОГИ, порядок указывается перед ними:
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Документ,
РеализацияТоваровУслуг.Дата КАК Дата,
РеализацияТоваровУслуг.СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Проведен
УПОРЯДОЧИТЬ ПО
Дата УБЫВ,
Сумма
Что здесь важно:
- 🔹 Направление — слова
ВОЗР(по умолчанию) иУБЫВ. Они относятся к одному полю, а не ко всей фразе: у каждого поля своё направление. - 🔹 Поля перечисляют через запятую, приоритет — слева направо.
- 🔹 Можно указать псевдоним из списка выбора (
Дата), а можно полный путь (РеализацияТоваровУслуг.Дата). - 🔹 Сортировать можно по реквизитам, которых нет в выборке, но тогда используйте полный путь через точку.
Сортировка по ссылке
Тут чаще всего и ошибаются. Если написать УПОРЯДОЧИТЬ ПО Номенклатура, где Номенклатура — ссылка, строки упорядочатся по внутреннему значению ссылки. Человеку этот порядок покажется случайным. Есть два способа:
- взять реквизит ссылки:
УПОРЯДОЧИТЬ ПО Номенклатура.Наименование; - добавить
АВТОУПОРЯДОЧИВАНИЕв конец запроса.
Первый способ точнее: вы сами выбираете, по чему сортировать. Второй короче, но порядок зависит от настроек объекта метаданных.
Первые N записей и объединения
Связка ВЫБРАТЬ ПЕРВЫЕ 10 без УПОРЯДОЧИТЬ ПО возвращает «какие-то» десять строк. Для «десяти последних документов» порядок обязателен: УПОРЯДОЧИТЬ ПО Дата УБЫВ.
При ОБЪЕДИНИТЬ ВСЕ сортировка пишется один раз — в самом конце, после последнего запроса пакета объединения, и действует на результат целиком. Имена полей берутся из первого запроса объединения. Если назвать поле в порядке именем из второго запроса, получите ошибку «поле не найдено».
Сложная логика: временные таблицы и порядок
Во временной таблице порядок строк не гарантируется, даже если вы написали УПОРЯДОЧИТЬ ПО при помещении. Исключение — ПЕРВЫЕ N: там порядок определяет, какие N строк попадут в таблицу, но не порядок строк в ней при дальнейшем чтении.
Правило простое: сортируйте в последнем запросе пакета, который отдаёт результат.
ВЫБРАТЬ
ДвиженияТоваров.Номенклатура КАК Номенклатура,
СУММА(ДвиженияТоваров.Количество) КАК Количество
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ДвиженияТоваров
СГРУППИРОВАТЬ ПО
ДвиженияТоваров.Номенклатура
;
////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Остатки.Номенклатура КАК Номенклатура,
ВТ_Остатки.Количество КАК Количество
ИЗ
ВТ_Остатки КАК ВТ_Остатки
УПОРЯДОЧИТЬ ПО
Количество УБЫВ,
ВТ_Остатки.Номенклатура.Наименование
Пакет выполняется подряд, запрос с ПОМЕСТИТЬ результата не отдаёт. Если после Запрос.ВыполнитьПакет() нужна выборка, берите результат нужного запроса по индексу (счёт идёт с нуля): в примере выше это Результат[1].Выбрать(). Если же вызвать Запрос.Выполнить(), вернётся результат последнего запроса пакета.
Когда порядок нужен внутри временной таблицы
Бывает, что сортировку нужно «закрепить» в промежуточных данных — например, чтобы взять по каждому контрагенту последнюю запись. Для этого используют не сортировку, а функции получения последней записи или соединение с агрегатом МАКСИМУМ(Период). Порядок строк во временной таблице — не механизм хранения порядка.
Сортировка в СКД: настройки, схема и код
В отчётах на СКД запрос — лишь поставщик данных. Итоговый порядок строк определяют настройки компоновки.
Через конструктор схемы
- Откройте схему компоновки данных отчёта.
- Перейдите на вкладку
Настройки. - В дереве структуры выберите нужную группировку (или корневой элемент
Отчёт). - Внизу переключитесь на вкладку
Порядок. - Добавьте поле и выберите направление.
Если у группировки нет собственного порядка, он берётся с вышестоящего уровня. Это удобно: один раз задали порядок на корне, и он действует на все вложенные группировки.
Поле должно быть среди доступных полей схемы. Если вы дописали поле только в текст запроса, но не обновили список полей набора данных, в настройках его не будет. Откройте набор данных и нажмите Добавить поле или пересоздайте поля из запроса.
Через код
Пользователи часто хотят, чтобы сортировка задавалась по условию — например, по выбору из формы. Тогда её добавляют программно в настройки компоновщика:
Порядок = КомпоновщикНастроек.Настройки.Порядок;
Порядок.Элементы.Очистить();
Элемент = Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
Элемент.Поле = Новый ПолеКомпоновкиДанных("Дата");
Элемент.ТипУпорядочивания = НаправлениеУпорядочиванияКомпоновкиДанных.Убывание;
Элемент.Использование = Истина;
Это порядок на корневом уровне. Для порядка внутри группировки обращайтесь к Настройки.Структура[0].Порядок.
Сортировка по нескольким полям
Добавляйте элементы подряд: первый — главный. Если одно из полей — ссылка, СКД сама упорядочит значения по представлению (если нет особых настроек). Поэтому в СКД АВТОУПОРЯДОЧИВАНИЕ в запрос дописывать, как правило, не нужно.
Таблица значений и динамический список в форме
Если данные уже получены и лежат в таблице значений, запрос не нужен. Для этого есть метод Сортировать:
ТаблицаЗначений.Сортировать("Дата Убыв, Номер");
Столбцы перечисляют через запятую, направление пишут после имени. Сортируется сама таблица, а не копия. Для списка значений есть СортироватьПоЗначению() и СортироватьПоПредставлению().
Запомните один нюанс: сортировка таблицы по столбцу со ссылками работает по тем же правилам, что и в запросе — не по тексту наименования. Чтобы упорядочить по наименованию, заведите в таблице отдельный столбец с этим текстом и сортируйте по нему.
Скорость: что делает сортировка с производительностью
Сортировка — дорогая операция, особенно на больших выборках. Что помогает:
| Приём | Когда применять | Что получаете |
|---|---|---|
Ограничение через ПЕРВЫЕ N | Нужны последние или самые крупные записи | Серверу не нужно упорядочивать всю выборку |
Фильтр в ГДЕ до сортировки | Всегда | Упорядочивается меньше строк |
| Индекс реквизита | Сортировка идёт по одному и тому же реквизиту каждый день | Быстрее порядок и поиск |
| Индексирование временной таблицы | Таблица большая и соединяется по ключу | Быстрее соединения и выборки |
| Сортировка в клиенте | Данных мало, порядок меняет пользователь | Меньше запросов к серверу |
Индекс реквизита
В конфигураторе откройте свойства реквизита справочника или документа. Свойство Индексировать включает индексирование; вариант с дополнительным упорядочиванием полезен для строковых реквизитов, которые часто используют в порядке. Лишние индексы замедляют запись и увеличивают размер базы, поэтому ставьте их только на те реквизиты, по которым реально сортируют и ищут.
Индексирование временной таблицы
Для временных таблиц есть фраза ИНДЕКСИРОВАТЬ ПО:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
Контрагенты.Наименование КАК Наименование
ПОМЕСТИТЬ ВТ_Контрагенты
ИЗ
Справочник.Контрагенты КАК Контрагенты
ИНДЕКСИРОВАТЬ ПО
Контрагент
Индекс стоит делать по полям, по которым таблицу соединяют с другими. Ради одной сортировки в последнем запросе он обычно не нужен.
Поля неограниченной длины
По реквизиту строки неограниченной длины сортировать нельзя. Приведите значение к ограниченной строке: ВЫРАЗИТЬ(Документ.Комментарий КАК СТРОКА(100)). Помните, что сортировка пойдёт только по первым ста символам.
Порядок в динамическом списке формы
Если нужно, чтобы пользователь сам менял порядок в списке формы, запрос не трогают. Откройте форму в конфигураторе, выделите реквизит с типом Динамический список и в его свойствах нажмите Настройка списка. Дальше путь тот же, что в СКД: вкладка Порядок, добавить поле, выбрать направление.
Отдельный случай — основной порядок списка справочника. Он задаётся в свойствах объекта метаданных: у справочника есть настройки ввода по строке и порядка по умолчанию (код или наименование). Если список открывается не в том порядке, сначала проверьте эти настройки, а уже потом лезьте в запрос.
В программно собранном динамическом списке порядок меняют так:
Список.Порядок.Элементы.Очистить();
Элемент = Список.Порядок.Элементы.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
Элемент.Поле = Новый ПолеКомпоновкиДанных("Наименование");
Элемент.ТипУпорядочивания = НаправлениеУпорядочиванияКомпоновкиДанных.Возрастание;
Элемент.Использование = Истина;
Здесь Список — имя реквизита формы с динамическим списком. Если реквизит назван иначе, подставьте своё имя.
Практический пример: отчёт, где порядок не совпадает с ожиданием
Типичная картина. Отчёт показывает продажи по контрагентам. Разработчик написал в запросе УПОРЯДОЧИТЬ ПО Сумма УБЫВ, а пользователь видит алфавитный порядок. Причина в СКД: в структуре отчёта у группировки Контрагент уже стоит порядок по наименованию, и он перекрывает запрос.
Что делать:
- Откройте схему, вкладку
Настройки, выберите группировкуКонтрагент. - На вкладке
Порядокзамените поле наСуммаи поставьте убывание. - Если порядок нужен и по умолчанию, и по выбору пользователя, разрешите его изменение: включите для элемента пользовательскую настройку, тогда он появится в окне настроек отчёта.
Проверьте результат на реальных данных. Тестовая база с тремя контрагентами порядок не покажет: на малой выборке любой порядок выглядит верным.
Числа в строках
Отдельная ловушка — номера документов и коды, которые хранятся строкой. При сортировке по возрастанию строка «10» окажется раньше «2», потому что сравниваются символы, а не числа. Если код всегда состоит из цифр, а длина разная, у справочника включают контроль длины и дополнение нулями слева. Для старых данных вариант — приведение в запросе: ВЫРАЗИТЬ(Код КАК Число(15, 0)). Но он сработает, только если во всех строках нет букв, иначе запрос завершится ошибкой преобразования. Сначала проверьте данные отбором.
Регистр букв и пустые значения
Сортировка строк в запросе зависит от настроек сортировки базы данных, а не от того, как вы пишете запрос. Поэтому регистр букв обычно не влияет на порядок, и «а» и «А» идут рядом. Пустые значения при возрастании оказываются вверху. Если пустых нужно показывать в конце, используйте условие в списке полей: добавьте поле ВЫБОР КОГДА Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК ПризнакПустого и сортируйте сначала по нему, потом по основному полю.
Частые ошибки при добавлении сортировки
Ошибки в этой теме повторяются от проекта к проекту:
- ⚠️ Порядок задан в запросе, а в СКД он «пропал». Настройки компоновки имеют приоритет: проверьте вкладку
Порядокв структуре отчёта. - ⚠️ Сортировка по ссылке выглядит хаотично. Добавьте реквизит
.НаименованиеилиАВТОУПОРЯДОЧИВАНИЕ. - ⚠️ Поле не найдено в
УПОРЯДОЧИТЬ ПО. При объединении запросов используйте имена из первого запроса. - ⚠️ Ошибка при группировке. В сгруппированном запросе упорядочивать можно только по полям группировки и по агрегатным функциям. Остальные реквизиты нужно сначала включить в группировку.
- ⚠️ Направление применилось не ко всем полям.
УБЫВотносится к одному полю. Для каждого поля пишите своё. - ⚠️ Результат вообще не упорядочен. Проверьте, что
УПОРЯДОЧИТЬ ПОстоит в запросе, который вы читаете, а не в промежуточном.
Перед тем как править запрос, по которому строятся регламентные отчёты, сохраните его старый текст. Вернуться к нему проще, чем искать, какая именно фраза изменила порядок.
Частые вопросы
Можно ли сортировать по полю, которого нет в выборке?
УПОРЯДОЧИТЬ ПО Таблица.Реквизит.Как отсортировать по убыванию?
УБЫВ. В конструкторе запроса направление выбирается в колонке рядом с полем.Как отсортировать в обратном порядке уже готовую таблицу значений?
Сортировать("ИмяКолонки Убыв"). Если порядок нужен только на экране, удобнее сортировка в самой форме.Влияет ли сортировка на скорость отчёта?
ПЕРВЫЕ N.