В практике разработки на платформе 1С часто возникает задача: передать в запрос список элементов (например, Склады, Номенклатуру или Контрагентов) и получить результат именно в том порядке, в котором они были расположены в исходном СпискеЗначений или Массиве. По умолчанию СУБД возвращает данные в произвольном порядке или по индексам таблиц базы данных. Рассмотрим подробно несколько эффективных способов решения этой задачи: от простых программных методов до использования стандартных подсистем.
Этот метод считается наиболее профессиональным и гибким. Он позволяет передать в запрос любую последовательность и гарантированно получить её на выходе. Разберем по шагам алгоритм реализации:
ТаблицуЗначений с двумя колонками: ссылкой на объект и числовым полем для хранения индекса (порядка).Проанализируем пример кода:
// 1. Подготовка данных
ТаблицаПорядка = Новый ТаблицаЗначений;
ТаблицаПорядка.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.Склады"));
ТаблицаПорядка.Колонки.Добавить("Порядок", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0)));
Для Каждого ЭлементСписка Из ИсходныйСписокСкладов Цикл
НоваяСтрока = ТаблицаПорядка.Добавить();
НоваяСтрока.Ссылка = ЭлементСписка.Значение;
НоваяСтрока.Порядок = ИсходныйСписокСкладов.Индекс(ЭлементСписка);
КонецЦикла;
// 2. Выполнение запроса
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ_Порядок.Ссылка КАК Склад,
| ТЗ_Порядок.Порядок КАК НомерПорядка
|ПОМЕСТИТЬ ВТ_Порядок
|ИЗ
| &ТаблицаПорядка КАК ТЗ_Порядок
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Склады.Ссылка КАК Ссылка,
| Склады.Наименование КАК Наименование,
| ВТ_Порядок.НомерПорядка КАК НомерПорядка
|ИЗ
| Справочник.Склады КАК Склады
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Порядок КАК ВТ_Порядок
| ПО Склады.Ссылка = ВТ_Порядок.Склад
|
|УПОРЯДОЧИТЬ ПО
| НомерПорядка";
Запрос.УстановитьПараметр("ТаблицаПорядка", ТаблицаПорядка);
РезультатЗапроса = Запрос.Выполнить();
Этот способ позволяет избежать ограничений на количество элементов в списке и работает максимально быстро на уровне SQL-сервера.
Если список элементов небольшой и фиксированный (например, 3-5 складов), можно воспользоваться оператором ВЫБОР непосредственно в предложении УПОРЯДОЧИТЬ ПО. Рассмотрим ситуацию, когда нам нужно вывести определенные склады первыми:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Склады.Ссылка КАК Ссылка,
| Склады.Наименование КАК Наименование
|ИЗ
| Справочник.Склады КАК Склады
|ГДЕ
| Склады.Ссылка В(&СписокСкладов)
|
|УПОРЯДОЧИТЬ ПО
| ВЫБОР
| КОГДА Склады.Ссылка = &Склад1 ТОГДА 1
| КОГДА Склады.Ссылка = &Склад2 ТОГДА 2
| ИНАЧЕ 3
| КОНЕЦ";
Важный нюанс: Данный метод не рекомендуется использовать для больших списков (более 20-30 элементов), так как это значительно усложняет план выполнения запроса в СУБД и может привести к ошибкам парсинга при слишком большом количестве условий.
В современных конфигурациях на базе Библиотеки стандартных подсистем (БСП) предусмотрен штатный механизм для управления порядком. Если вам нужно, чтобы склады во всех отчетах всегда выводились в определенном пользовательском порядке, выполним следующие действия:
Порядок в справочнике. В типовых решениях (УТ 11, ERP) он часто уже встроен или может быть добавлен через расширение.Порядок.Этот подход освобождает программиста от необходимости "хардкодить" правила сортировки и передает управление бизнес-пользователям.
Выясним причину, по которой иногда программисты прибегают к нумерации в наименованиях. Обычно это происходит из-за невозможности быстро изменить конфигурацию. Однако в 1С есть механизм Дополнительных реквизитов и сведений, который позволяет решить задачу корректно:
Число с названием "ПриоритетСортировки".Разберем преимущество: это не портит наименования объектов (что важно для обменов с внешними системами) и позволяет легко менять приоритеты без участия разработчика.
Проанализируем ситуацию, когда данные выводятся в отчет. СКД умеет работать с внешними наборами данных. Если мы сначала программно подготовим ТаблицуЗначений, отсортируем её методом ТаблицаЗначений.Сортировать("Порядок Возр") и передадим в СКД, компоновщик сохранит этот порядок при выводе, если в настройках самого отчета не задана иная сортировка.
Также в СКД можно создать Вычисляемое поле, которое будет определять "вес" каждого элемента на основе переданного в параметры массива, используя функции языка выражений СКД.
Выбор метода зависит от конкретных условий задачи: