При доработке печатных форм и отчетов в конфигурациях 1С (например, 1С:Управление торговлей 10.3) разработчики часто сталкиваются с ошибкой синтаксиса запроса: «В случае использования операторов ОБЪЕДИНИТЬ, поля предложений УПОРЯДОЧИТЬ ПО и ИТОГИ ПО должны находиться в списке выбора».
Разберем подробно, почему возникает эта ошибка, какие правила языка запросов 1С нарушаются при составлении кода и как правильно исправить ситуацию на практических примерах.
Проанализируем механику работы платформы 1С при объединении нескольких таблиц с помощью конструкций ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ. Ошибка возникает в двух основных случаях:
ВЫБРАТЬ, участвующая в объединении, должна содержать строго одинаковое количество колонок. Если в первой выборке указано 11 полей, а во второй или третьей — 9 или 10, платформа не может сопоставить структуру результата и выдает ошибку.УПОРЯДОЧИТЬ ПО может обращаться только к тем полям и псевдонимам, которые явно присутствуют в самом первом блоке ВЫБРАТЬ (или во внешнем запросе, если объединение вынесено во вложенную таблицу). Если поле из УПОРЯДОЧИТЬ ПО сдвигается по позиции из-за пропущенных колонок в соседних ветках объединения, платформа не может его идентифицировать.Рассмотрим ситуацию, когда в запросе объединяются данные из нескольких табличных частей (например, «Товары», «Услуги» и «ВозвратнаяТара»). Чтобы запрос с оператором ОБЪЕДИНИТЬ ВСЕ и конструкцией УПОРЯДОЧИТЬ ПО работал корректно, необходимо синхронизировать состав всех выборок.
Посмотрим на пример правильного заполнения недостающих полей пустыми значениями NULL или фиктивными значениями в каждом блоке:
Запрос.Текст = "
|ВЫБРАТЬ
| ВложенныйЗапрос.Номенклатура КАK Номенклатура,
| ВЫРАЗИТЬ(ВложенныйЗапрос.Номенклатура.НаименованиеПолное КАK Строка(1000)) КАK НаименованиеПолное,
| ВложенныйЗапрос.Номенклатура.Код КАK Код,
| ВложенныйЗапрос.Номенклатура.Артикул КАK Артикул,
| ВложенныйЗапрос.Количество КАK Количество,
| ВложенныйЗапрос.ЕдиницаИзмерения.Представление КАK ЕдиницаИзмерения,
| ВложенныйЗапрос.Размещение КАK Размещение,
| ВложенныйЗапрос.Характеристика КАK Характеристика,
| NULL КАK Серия,
| ВложенныйЗапрос.НомерСтроки КАK НомерСтроки,
| ВложенныйЗапрос.Метка КАK Метка
|ИЗ
| (ВЫБРАТЬ
| ЗаказПокупателя.Номенклатура КАK Номенклатура,
| ЗаказПокупателя.ЕдиницаИзмерения КАK ЕдиницаИзмерения,
| ЗаказПокупателя.Размещение КАK Размещение,
| СУММА(ЗаказПокупателя.Количество) КАK Количество,
| ЗаказПокупателя.ХарактеристикаНоменклатуры КАK Характеристика,
| МИНИМУМ(ЗаказПокупателя.НомерСтроки) КАK НомерСтроки,
| 0 КАK Метка
| ИЗ
| Документ.ЗаказПокупателя.Товары КАK ЗаказПокупателя
| ГДЕ
| ЗаказПокупателя.Ссылка = &ТекущийДокумент
| СГРУППИРОВАТЬ ПО
| ЗаказПокупателя.Номенклатура,
| ЗаказПокупателя.ЕдиницаИзмерения,
| ЗаказПокупателя.Размещение,
| ЗаказПокупателя.ХарактеристикаНоменклатуры) КАK ВложенныйЗапрос
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ЗаказПокупателя.Номенклатура КАK Номенклатура,
| ПРЕДСТАВЛЕНИЕ(ЗаказПокупателя.Номенклатура) КАK НаименованиеПолное,
| ЗаказПокупателя.Номенклатура.Код КАK Код,
| ЗаказПокупателя.Номенклатура.Артикул КАK Артикул,
| ЗаказПокупателя.Количество КАK Количество,
| ЗаказПокупателя.Номенклатура.ЕдиницаХраненияОстатков КАK ЕдиницаИзмерения,
| NULL КАK Размещение,
| NULL КАK Характеристика,
| NULL КАK Серия,
| ЗаказПокупателя.НомерСтроки КАK НомерСтроки,
| 1 КАK Метка
|ИЗ
| Документ.ЗаказПокупателя.Услуги КАK ЗаказПокупателя
|ГДЕ
| ЗаказПокупателя.Ссылка = &ТекущийДокумент
|
|УПОРЯДОЧИТЬ ПО
| Метка ВОЗР,
| НомерСтроки ВОЗР
|";
Обратим внимание: во втором блоке объединения (выборка услуг) явным образом добавлены отсутствующие поля NULL КАK Размещение, NULL КАK Характеристика и NULL КАK Серия. Порядок и количество колонок полностью совпадают с первым блоком, благодаря чему платформа свободно выполняет сортировку по полям Метка и НомерСтроки.
Проанализируем бизнес-задачу. Очень часто при создании специализированных документов (например, сборочного листа для склада) услуги или возвратная тара на печать выводиться не должны. В этом случае объединение с другими табличными частями оказывается лишним.
Если исключить ненужные операторы ОБЪЕДИНИТЬ ВСЕ, структура запроса существенно упрощается, а риск получения ошибок синтаксиса сводится к нулю:
Запрос.Текст = "
|ВЫБРАТЬ
| ВложенныйЗапрос.Номенклатура КАK Номенклатура,
| ВЫРАЗИТЬ(ВложенныйЗапрос.Номенклатура.НаименованиеПолное КАK Строка(1000)) КАK НаименованиеПолное,
| ВложенныйЗапрос.Номенклатура.Код КАK Код,
| ВложенныйЗапрос.Номенклатура.Артикул КАK Артикул,
| ВложенныйЗапрос.Количество КАK Количество,
| ВложенныйЗапрос.ЕдиницаИзмерения.Представление КАK ЕдиницаИзмерения,
| ВложенныйЗапрос.Размещение КАK Размещение,
| ВложенныйЗапрос.Характеристика КАK Характеристика,
| NULL КАK Серия,
| ВложенныйЗапрос.НомерСтроки КАK НомерСтроки,
| ВложенныйЗапрос.Метка КАK Метка
|ИЗ
| (ВЫБРАТЬ
| ЗаказПокупателя.Номенклатура КАK Номенклатура,
| ЗаказПокупателя.ЕдиницаИзмерения КАK ЕдиницаИзмерения,
| ЗаказПокупателя.Размещение КАK Размещение,
| СУММА(ЗаказПокупателя.Количество) КАK Количество,
| ЗаказПокупателя.ХарактеристикаНоменклатуры КАK Характеристика,
| МИНИМУМ(ЗаказПокупателя.НомерСтроки) КАK НомерСтроки,
| 0 КАK Метка
| ИЗ
| Документ.ЗаказПокупателя.Товары КАK ЗаказПокупателя
| ГДЕ
| ЗаказПокупателя.Ссылка = &ТекущийДокумент
| СГРУППИРОВАТЬ ПО
| ЗаказПокупателя.Номенклатура,
| ЗаказПокупателя.ЕдиницаИзмерения,
| ЗаказПокупателя.Размещение,
| ЗаказПокупателя.ХарактеристикаНоменклатуры) КАK ВложенныйЗапрос
|
|УПОРЯДОЧИТЬ ПО
| Метка ВОЗР,
| НомерСтроки ВОЗР
|";
ОБЪЕДИНИТЬ ВСЕ внутри вложенных запросов эффективнее помещать промежуточные данные во временную таблицу (конструкция ПОМЕСТИТЬ ВТ_Данные), а затем выполнять итоговую выборку с предложенными условиями и сортировкой.NULL следите за тем, чтобы в ветках с реальными данными тип поля приводился к нужному виду с помощью функции ВЫРАЗИТЬ(), если это необходимо для правильной работы группировок или сортировок.