Почему возникает ошибка «поля предложений УПОРЯДОЧИТЬ ПО должны находиться в списке выбора» при объединении запросов в 1С?

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

При доработке типовых запросов (например, при модификации алгоритмов печати накладных ТОРГ-12 или актов) разработчики часто сталкиваются с ситуацией: после добавления нового поля или использования функции ВЫРАЗИТЬ запрос перестает выполняться. Платформа 1С выдает сообщение об ошибке:

«В случае использования операторов ОБЪЕДИНИТЬ, поля предложений УПОРЯДОЧИТЬ ПО и ИТОГИ ПО должны находиться в списке выбора».

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

Анализ проблемы и позиционное сопоставление полей

Разберем, как платформа 1С обрабатывает конструкции с объединением результатов нескольких выборок:

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

Пошаговое исправление структуры запроса

Разберем по шагам, как правильно добавить новые поля в объединенный запрос, чтобы избежать подобных сбоев.

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

    Посмотрим на фрагмент структуры колонок первой ветки:

    
    ВЫБРАТЬ
        ВложенныйЗапрос.Номенклатура КАК Номенклатура,
        ВЫРАЗИТЬ(ВложенныйЗапрос.Номенклатура.НаименованиеПолное КАК Строка(150)) КАК ТоварНаименование,
        ВложенныйЗапрос.яАналогН КАК яАналогН,
        ВЫРАЗИТЬ(ВложенныйЗапрос.яАналогН.НаименованиеПолное КАК Строка(150)) КАК яАналогНоменклатура,
        ВложенныйЗапрос.ЕдиницаИзмерения КАК ЕдиницаИзмерения
    ...
    

    Во второй ветке (секция Услуги) и третьей ветке (секция ВозвратнаяТара) мы обязаны разместить поля строго на тех же позициях:

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

    ВЫРАЗИТЬ("" КАК Строка(150)) КАК яАналогНоменклатура

    Либо внутри основного запроса можно использовать конструкцию проверки на пустоту:

    
    ВЫБОР
        КОГДА ВложенныйЗапрос.яАналогН ЕСТЬ NULL
            ТОГДА ВЫРАЗИТЬ("" КАК Строка(150))
        ИНАЧЕ ВЫРАЗИТЬ(ВложенныйЗапрос.яАналогН.НаименованиеПолное КАК Строка(150))
    КОНЕЦ КАК яАналогНоменклатура
    
  3. Проверяем разыменование полей через точку. Обращение к реквизитам через точку от полей вложенного запроса вида ВложенныйЗапрос.яАналогН.НаименованиеПолное заставляет СУБД строить дополнительное левое соединение с таблицей справочника уже после формирования вложенного запроса. Чтобы повысить производительность и упростить логику, разыменование ссылок и вызов ВЫРАЗИТЬ рекомендуется выполнять непосредственно в исходной табличной части внутри подзапроса или предварительно выгружать данные во временную таблицу.

Рекомендация по использованию конструктора запросов

При ручной правке сложных текстов с множественными операторами ОБЪЕДИНИТЬ ВСЕ легко допустить опечатку и сбить очередность полей. Рекомендуется открывать такие запросы в визуальном Конструкторе запросов на закладке «Объединения/Псевдонимы».

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

← На главную