При разработке отчетов, обработок и печатных форм в 1С разработчики нередко сталкиваются с ситуацией, когда данные табличной части документа выбираются запросом в произвольном порядке, отличном от исходного расположения строк в документе. Разберем, почему простой запрос может возвращать перемешанные строки при добавлении определенных полей и как гарантировать правильный порядок вывода данных.
Рассмотрим типовой пример запроса к табличной части документа, в котором не указана секция сортировки:
ВЫБРАТЬ
Док.НомерСтроки КАК НомерСтроки,
Док.Номенклатура.НаименованиеПолное КАК Номенклатура,
Док.ЕдиницаИзмерения.Наименование КАК ЕдиницаИзмерения,
Док.ЕдиницаИзмерения.ЕдиницаПоКлассификатору.Код КАК ЕдиницаИзмеренияКод,
Док.Количество КАК Количество
ИЗ
Документ.НалоговаяНакладная.Товары КАК Док
ГДЕ
Док.Ссылка = &Ссылка
На первый взгляд кажется, что строки должны вернуться строго по возрастанию поля НомерСтроки. Однако на практике строки часто оказываются перемешанными. При этом, если исключить из выборки обращение к реквизиту Док.ЕдиницаИзмерения.ЕдиницаПоКлассификатору.Код, результат снова начинает возвращаться в исходном порядке.
Проанализируем технические процессы, происходящие на уровне СУБД и механизма трансляции запросов платформы 1С:
УПОРЯДОЧИТЬ ПО (или ORDER BY на уровне SQL), СУБД имеет право возвращать записи в абсолютно любом порядке.Док.ЕдиницаИзмерения.ЕдиницаПоКлассификатору.Код) транслируется платформой 1С в физические конструкции LEFT OUTER JOIN к соответствующим таблицам справочников. При многоуровневом обращении формируется каскад из нескольких последовательных левых соединений.Hash Match или параллельную обработку), в результате чего исходная последовательность строк нарушается.Важно понимать: совпадение порядка строк в выборке без явного указания сортировки является лишь случайным следствием текущего плана выполнения СУБД. После обновления статистики, реструктуризации таблиц или изменения объема данных порядок строк может измениться в любой момент.
Основным и наиболее надежным решением является явное указание инструкции УПОРЯДОЧИТЬ ПО в конце запроса. Добавим упорядочивание по номеру строки документа:
ВЫБРАТЬ
Док.НомерСтроки КАК НомерСтроки,
Док.Номенклатура.НаименованиеПолное КАК Номенклатура,
Док.ЕдиницаИзмерения.Наименование КАК ЕдиницаИзмерения,
Док.ЕдиницаИзмерения.ЕдиницаПоКлассификатору.Код КАК ЕдиницаИзмеренияКод,
Док.Количество КАК Количество
ИЗ
Документ.НалоговаяНакладная.Товары КАК Док
ГДЕ
Док.Ссылка = &Ссылка
УПОРЯДОЧИТЬ ПО
НомерСтроки ВОЗР
Если в запросе используются ссылочные поля и важно упорядочить их с учетом системных представлений и иерархии, можно применить ключевое слово АВТОУПОРЯДОЧИВАНИЕ, однако для сохранения физической последовательности строк табличной части документа всегда следует явно указывать УПОРЯДОЧИТЬ ПО Док.НомерСтроки.
Если запрос расположен в типовом закрытом модуле конфигурации или его прямой текст невозможно отредактировать по условиям сопровождения, упорядочим полученные данные программно после выполнения запроса. Для этого выгрузим результат в таблицу значений и применим метод Сортировать():
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();
ТаблицаДанных.Сортировать("НомерСтроки Возр");
Для Каждого Стр Из ТаблицаДанных Цикл
// Обработка строк с гарантированным сохранением порядка
КонецЦикла;
В современных типовых конфигурациях при обнаружении подобных ошибок в типовых алгоритмах формирования печатных форм рекомендуется использовать механизм расширения конфигурации. Разберем, как исправить алгоритм через перехват метода с помощью аннотации &ИзменениеИКонтроль или &Вместо:
&Вместо("СформироватьПечатнуюФорму")
Функция Расш1_СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
// В переопределенном коде запроса добавляем секцию сортировки
// УПОРЯДОЧИТЬ ПО Док.НомерСтроки
// ...
КонецФункции
Для обеспечения максимального быстродействия и предсказуемости планов выполнения СУБД рекомендуется придерживаться стандартов разработки платформы 1С:
Док.ЕдиницаИзмерения.ЕдиницаПоКлассификатору.Код создает избыточные неявные соединения. Если требуется получить вложенные реквизиты, используйте явные секции ЛЕВОЕ СОЕДИНЕНИЕ.УПОРЯДОЧИТЬ ПО обязательна к применению.