Почему запрос 1С не сортирует вложенные таблицы и как это исправить

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет IT и автоматизация бизнеса
← На главную

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

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

Разберем причину: почему сортировка не работает?

Давайте проанализируем ситуацию с точки зрения архитектуры СУБД и платформы 1С. Когда мы пишем запрос вида ВЫБРАТЬ Ссылка, Запасы.(НомерСтроки, Номенклатура) ИЗ Документ.ЗаказПокупателя, платформа не создает один плоский набор данных. Она формирует иерархическую структуру.

Основная причина отсутствия сортировки заключается в следующем:

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

Рассмотрим пример кода, который часто вызывает вопросы:


ВЫБРАТЬ
    ЗаказПокупателя.Ссылка КАК Ссылка,
    ЗаказПокупателя.Запасы.(
        НомерСтроки КАК НомерСтроки,
        Номенклатура КАК Номенклатура,
        Количество КАК Количество
    ) КАК ТаблицаЗапасы
ИЗ
    Документ.ЗаказПокупателя КАК ЗаказПокупателя
ГДЕ
    ЗаказПокупателя.Ссылка = &ЗаказПокупателя
УПОРЯДОЧИТЬ ПО
    Ссылка,
    НомерСтроки

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

Решение 1: Использование плоского запроса к табличной части

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

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


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

Преимущества этого метода:

Решение 2: Сортировка в коде после выполнения запроса

Если специфика вашей задачи (например, сложная печатная форма или интеграция) требует сохранения структуры с вложенными таблицами, мы можем применить сортировку программно. Метод Выгрузить() для результата запроса позволяет получить таблицу значений, в колонках которой будут находиться другие таблицы значений (вложенные).

Проанализируем пример обхода и сортировки:


РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультат = РезультатЗапроса.Выгрузить();

Для Каждого СтрокаДокумент Из ТаблицаРезультат Цикл
    // Получаем вложенную таблицу из колонки
    ТаблицаЗапасы = СтрокаДокумент.ТаблицаЗапасы;
    
    // Сортируем её по номеру строки или любому другому полю
    ТаблицаЗапасы.Сортировать("НомерСтроки Возр");
    
    // Теперь данные внутри строки отсортированы
КонецЦикла;

Этот способ удобен тем, что вы сохраняете иерархическую структуру данных, но платите за это дополнительным временем на итерацию по строкам и перестроение коллекций в памяти сервера.

Решение 3: Система компоновки данных (СКД)

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

Рассмотрим алгоритм действий в СКД:

  1. Создаем Набор данных 1 (Запросы), где выбираем только шапку документов.
  2. Создаем Набор данных 2 (Запросы), где выбираем строки табличной части (Запасы).
  3. На закладке Связи наборов данных связываем их по полю Ссылка.
  4. В настройках отчета для детальных записей Набора данных 2 указываем нужную сортировку в стандартной вкладке Сортировка.

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

Важное замечание про поле НомерСтроки

Стоит отметить, что в некоторых типовых запросах 1С (в том числе в УНФ) поле НомерСтроки все же включают в секцию УПОРЯДОЧИТЬ ПО. Зачем это делается, если сортировка не работает? Часто это "задел" для Построителя отчета или Построителя выходных форм. Эти механизмы могут анализировать текст запроса и автоматически применять настройки сортировки к результату, если он обходится определенным образом. Однако при обычном программном выполнении Запрос.Выполнить().Выбрать() надеяться на это не стоит.

Резюме

Мы выяснили, что вложенные таблицы в запросах 1С — это удобный инструмент для получения иерархии, но они крайне ограничены в вопросах управления порядком строк. Для решения проблемы сортировки:

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

← На главную