В процессе разработки в 1С часто возникает задача получить данные запросом и обработать их в определенном порядке. Стандартная сортировка с помощью УПОРЯДОЧИТЬ ПО отлично справляется с алфавитным или числовым упорядочиванием. Но что делать, если нам нужно, чтобы одна конкретная запись, например, склад из текущего документа, всегда была первой в выборке, а остальные шли уже после нее? Рассмотрим эту задачу и разберем наиболее эффективные способы ее решения.
Проанализируем типичную ситуацию: у нас есть запрос, который получает остатки товара по всем складам. При проведении документа нам нужно в первую очередь обработать остатки на складе, указанном в этом документе. Для этого он должен быть первым в результате запроса.
Самый простой и элегантный способ решить эту задачу — создать в запросе вычисляемое (виртуальное) поле, которое будет служить индикатором для сортировки. Мы присвоим этому полю одно значение (например, 0) для "нашей" записи и другое значение (например, 1) для всех остальных. Затем отсортируем результат по этому новому полю.
Давайте по шагам разберем, как это работает на примере исходного запроса.
Исходный запрос:
ВЫБРАТЬ
ТоварыНаСкладеОстатки.Склад КАК Склад,
ТоварыНаСкладеОстатки.КоличествоОстаток КАК Количество
ИЗ
РегистрНакопления.ТоварыНаСкладе.Остатки(, Номенклатура = &Номенклатура) КАК ТоварыНаСкладеОстатки
Чтобы добавить нужную нам сортировку, модифицируем запрос следующим образом:
ВЫБРАТЬ конструкцию ВЫБОР.&НужныйСклад).ИНАЧЕ) присвоим значение 1.ПолеУпорядочивания.УПОРЯДОЧИТЬ ПО и укажем в ней наше новое поле.Итоговый запрос с сортировкой:
ВЫБРАТЬ
ТоварыНаСкладеОстатки.Склад КАК Склад,
ТоварыНаСкладеОстатки.КоличествоОстаток КАК Количество,
ВЫБОР
КОГДА ТоварыНаСкладеОстатки.Склад = &НужныйСклад
ТОГДА 0
ИНАЧЕ 1
КОНЕЦ КАК ПолеУпорядочивания
ИЗ
РегистрНакопления.ТоварыНаСкладе.Остатки(, Номенклатура = &Номенклатура) КАК ТоварыНаСкладеОстатки
УПОРЯДОЧИТЬ ПО
ПолеУпорядочивания
Как это работает? Платформа 1С при выполнении запроса сначала отсортирует все записи по полю ПолеУпорядочивания. Так как 0 меньше 1, запись, для которой условие выполнилось (т.е. наш нужный склад), окажется наверху списка. Все остальные записи получат значение 1 и будут идти после нее.
Метод с использованием ВЫБОР КОГДА очень гибок. Его можно применять не только для двух уровней приоритета ("нужный" и "все остальные"), но и для более сложных сценариев.
Предположим, у нас есть три уровня приоритета:
&НужныйСклад).&ОсновнойСклад).Для этого мы просто расширим конструкцию ВЫБОР и добавим дополнительное поле в секцию сортировки.
ВЫБРАТЬ
ТоварыНаСкладеОстатки.Склад КАК Склад,
ТоварыНаСкладеОстатки.КоличествоОстаток КАК Количество
ИЗ
РегистрНакопления.ТоварыНаСкладе.Остатки(, Номенклатура = &Номенклатура) КАК ТоварыНаСкладеОстатки
УПОРЯДОЧИТЬ ПО
ВЫБОР
КОГДА ТоварыНаСкладеОстатки.Склад = &НужныйСклад ТОГДА 0
КОГДА ТоварыНаСкладеОстатки.Склад = &ОсновнойСклад ТОГДА 1
ИНАЧЕ 2
КОНЕЦ,
Склад
В этом примере мы создали три уровня приоритета (0, 1, 2). Обратите внимание на второе поле в секции УПОРЯДОЧИТЬ ПО — Склад. Оно нужно для того, чтобы все записи с одинаковым приоритетом (в данном случае, все склады с приоритетом 2) были между собой отсортированы по наименованию. Без этого их порядок был бы непредсказуем.
Для еще более сложных или динамических сценариев сортировки можно использовать временные таблицы. Этот метод чуть более громоздкий, но дает больше контроля, когда логика определения приоритетов сложна.
Процесс состоит из двух шагов.
Шаг 1. Создание временной таблицы с приоритетами.
Сначала мы создаем временную таблицу, в которую помещаем склады и их порядковые номера для сортировки. Для этого используем пакетный запрос.
ВЫБРАТЬ
&НужныйСклад КАК Склад,
0 КАК ПорядокСортировки
ПОМЕСТИТЬ ПриоритетыСкладов
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Склады.Ссылка,
1
ИЗ
Справочник.Склады КАК Склады
ГДЕ
Склады.Ссылка <> &НужныйСклад
;
Шаг 2. Соединение с основной выборкой и сортировка.
Теперь основной запрос получения остатков мы соединяем с нашей временной таблицей ПриоритетыСкладов и сортируем по полю ПорядокСортировки.
ВЫБРАТЬ
Остатки.Склад КАК Склад,
Остатки.КоличествоОстаток КАК Количество
ИЗ
РегистрНакопления.ТоварыНаСкладе.Остатки(, Номенклатура = &Номенклатура) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыСкладов КАК Приоритеты
ПО Остатки.Склад = Приоритеты.Склад
УПОРЯДОЧИТЬ ПО
Приоритеты.ПорядокСортировки
Этот метод полезен, когда список приоритетных значений может быть большим или формируется динамически на основе других данных.
В завершение давайте сформулируем несколько важных правил при работе с сортировкой в запросах 1С.
УПОРЯДОЧИТЬ ПО порядок строк в результате запроса не гарантирован и может меняться от запуска к запуску или после обновления платформы.УПОРЯДОЧИТЬ ПО Поле1, Поле2) для вложенной сортировки.Таким образом, для решения задачи по выставлению нужной записи на первое место в результате запроса, конструкция ВЫБОР КОГДА является самым простым, эффективным и читаемым инструментом.