При модификации текстов запросов разработчики часто сталкиваются с ситуацией: достаточно убрать агрегатную функцию с числового поля (например, убрать СУММА), как платформа перестает выполнять запрос и выдает исключение вида «Поле не входит в группу...». Проанализируем, почему возникает такое поведение платформы и как правильно скорректировать запрос.
В реляционных базах данных и встроенном языке запросов 1С действует строгое синтаксическое правило: если в запросе присутствует предложение СГРУППИРОВАТЬ ПО, то каждое поле из секции ВЫБРАТЬ обязано либо быть свернуто агрегатной функцией, либо присутствовать в списке группировки.
К агрегатным функциям в 1С относятся:
СУММА — подсчет суммы числовых значений;КОЛИЧЕСТВО — подсчет количества записей (или различных записей);МАКСИМУМ — выбор максимального значения;МИНИМУМ — выбор минимального значения;СРЕДНЕЕ — расчет среднего арифметического.Посмотрим на пример из подзапроса временной таблицы ВТТехОперации, где возникла ошибка:
ВЫБРАТЬ
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
МИНИМУМ(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Расценка) КАК Расценка,
СУММА(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Сумма) КАК Сумма,
ЗначенияСвойствОбъектов.Значение,
(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Количество) КАК Количество
ПОМЕСТИТЬ ВТТехОперации
ИЗ
Документ.ОтчетПроизводстваЗаСмену.ТехнологическиеОперации КАК ОтчетПроизводстваЗаСменуТехнологическиеОперации
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
ПО ОтчетПроизводстваЗаСменуТехнологическиеОперации.Проект = ЗначенияСвойствОбъектов.Объект
СГРУППИРОВАТЬ ПО
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ЗначенияСвойствОбъектов.Значение
;
Как только с поля Количество была снята функция СУММА, СУБД больше не понимает, как именно сгруппировать строки: значений количества в документе по одной операции может быть несколько, а в секции СГРУППИРОВАТЬ ПО поле не объявлено. Система не может определить, какое именно значение подставить в объединенную строку, и генерирует ошибку выполнения.
Разберем основные варианты исправления запроса в зависимости от того, какой бизнес-результат требуется получить.
Если требуется вывести поле без агрегации, добавим его имя в список секции СГРУППИРОВАТЬ ПО. Разберем по шагам, как будет выглядеть фрагмент запроса:
ВЫБРАТЬ
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
МИНИМУМ(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Расценка) КАК Расценка,
СУММА(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Сумма) КАК Сумма,
ЗначенияСвойствОбъектов.Значение,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Количество КАК Количество
ПОМЕСТИТЬ ВТТехОперации
ИЗ
Документ.ОтчетПроизводстваЗаСмену.ТехнологическиеОперации КАК ОтчетПроизводстваЗаСменуТехнологическиеОперации
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
ПО ОтчетПроизводстваЗаСменуТехнологическиеОперации.Проект = ЗначенияСвойствОбъектов.Объект
СГРУППИРОВАТЬ ПО
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ЗначенияСвойствОбъектов.Значение,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Количество
;
Важный нюанс: при добавлении числового показателя в группировку изменится детализация выборки. Если в документе есть две строки с одинаковой технологической операцией, но разным количеством (например, 5 и 10), они перестанут схлопываться в одну строку и попадут в результат раздельно.
Часто разработчики убирают СУММА, когда не хотят, чтобы числовое поле суммировалось (например, если количество дублируется из-за соединений таблиц или представляет собой фиксированную норму). В таком случае правильным решением будет замена СУММА на МАКСИМУМ или МИНИМУМ:
ВЫБРАТЬ
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
МИНИМУМ(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Расценка) КАК Расценка,
СУММА(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Сумма) КАК Сумма,
ЗначенияСвойствОбъектов.Значение,
МАКСИМУМ(ОтчетПроизводстваЗаСменуТехнологическиеОперации.Количество) КАК Количество
ПОМЕСТИТЬ ВТТехОперации
...
В этом случае структура группировки сохраняется, детальность выборки не нарушается, а синтаксис запроса полностью удовлетворяет требованиям платформы.
Если задача состоит в получении точных детальных записей табличной части документа без объединения строк, следует отказаться от группировки в этой временной таблице полностью. Для этого удалим все агрегатные функции и само предложение СГРУППИРОВАТЬ ПО:
ВЫБРАТЬ
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Ссылка,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.ТехнологическаяОперация,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Расценка КАК Расценка,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Сумма КАК Сумма,
ЗначенияСвойствОбъектов.Значение,
ОтчетПроизводстваЗаСменуТехнологическиеОперации.Количество КАК Количество
ПОМЕСТИТЬ ВТТехОперации
ИЗ
Документ.ОтчетПроизводстваЗаСмену.ТехнологическиеОперации КАК ОтчетПроизводстваЗаСменуТехнологическиеОперации
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
ПО ОтчетПроизводстваЗаСменуТехнологическиеОперации.Проект = ЗначенияСвойствОбъектов.Объект
;
Если при этом требуется лишь исключить дублирование строк, возникшее при левом соединении с регистром сведений, вместо группировки используем конструкцию ВЫБРАТЬ РАЗЛИЧНЫЕ.
Рассмотрим дополнительные рекомендации, которые помогут повысить стабильность и быстродействие подобных пакетных запросов:
ВТПродукция, ВТРаспределение и ВТТехОперации в итоговом запросе связываются между собой по полям Ссылка и ТехнологическаяОперация. При создании временных таблиц рекомендуется добавлять конструкцию ИНДЕКСИРОВАТЬ ПО Ссылка, ТехнологическаяОперация, что существенно ускоряет операцию левого соединения в СУБД.ВТПродукция.Ссылка.Дата МЕЖДУ &Дата1 И &Дата2 наложено только в финальной выборке. Гораздо эффективнее перенести фильтрацию по дате документа непосредственно в секцию ГДЕ каждого исходного подзапроса пакета. Это предотвратит считывание лишних данных из базы в промежуточные временные таблицы.