Почему при упорядочивании по коду счета в запросе 1С возникает ошибка «Поле не входит в группу»?

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

При разработке сложных отчетов на платформе 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда визуально корректный запрос отказывается выполняться. Типичный сценарий: вы используете группировку по строковому коду счета (например, Хозрасчетный.Код), и запрос работает прекрасно, пока вы не добавляете инструкцию УПОРЯДОЧИТЬ ПО. В этот момент система выдает ошибку: «Поле не входит в группу "Хозрасчетный.Код"», несмотря на то, что это поле явно указано в секции СГРУППИРОВАТЬ ПО.

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

Анализ проблемного запроса

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


ВЫБРАТЬ
    СУММА(ХозрасчетныйОстатки.СуммаОстатокДт) КАК ОстатокДт,
    ХозрасчетныйОстатки.Счет.Код КАК КодСчета
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , , ) КАК ХозрасчетныйОстатки

СГРУППИРОВАТЬ ПО
    ХозрасчетныйОстатки.Счет.Код

УПОРЯДОЧИТЬ ПО
    КодСчета

На первый взгляд, все логично: поле КодСчета присутствует в выборке и в группировке. Однако при выполнении этого кода (или при открытии его в конструкторе запроса) 1С выдает ошибку. Проблема кроется в том, как транслятор запросов 1С преобразует этот код в инструкции для SQL-сервера.

Причина №1: Скрытое поле «Порядок» (OrderField)

Выясним, как устроены планы счетов в 1С. В метаданных любого плана счетов существует свойство «Способ упорядочивания». Чаще всего это упорядочивание по коду. Но для СУБД (MS SQL, PostgreSQL и др.) обычная строка кода не всегда позволяет выстроить счета в правильном иерархическом порядке (например, чтобы счет «20.01» шел после «20»).

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

Причина №2: Обращение через точку (Dereferencing)

Рассмотрим подробнее конструкцию ХозрасчетныйОстатки.Счет.Код. В терминах 1С это обращение «через точку». Платформа обрабатывает такие обращения следующим образом:

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

Поскольку в блоке СГРУППИРОВАТЬ ПО указана только строка (Код), а не сама Ссылка, платформа теряет контекст объекта и не может гарантировать правильную сортировку по правилам плана счетов.

Решение №1: Группировка по ссылке (Рекомендуемое)

Самый простой и эффективный способ исправить ошибку — добавить Ссылка в блок группировки. Проанализируем исправленный вариант:


ВЫБРАТЬ
    СУММА(ХозрасчетныйОстатки.СуммаОстатокДт) КАК ОстатокДт,
    ХозрасчетныйОстатки.Счет.Код КАК КодСчета,
    ХозрасчетныйОстатки.Счет КАК СчетСсылка
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , , ) КАК ХозрасчетныйОстатки

СГРУППИРОВАТЬ ПО
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.Счет.Код

УПОРЯДОЧИТЬ ПО
    КодСчета

Почему это работает? Когда в группировке участвует поле типа ПланСчетовСсылка, платформа получает «карт-бланш» на использование любых связанных с этой ссылкой полей в секции ORDER BY. Теперь генератор SQL-запросов может свободно добавлять поле OrderField, так как оно функционально зависит от Ссылки, и запрос становится корректным с точки зрения реляционной логики.

Решение №2: Использование вложенных запросов или временных таблиц

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

  1. Сначала сгруппируем данные по Ссылке во временную таблицу.
  2. Затем выберем данные из временной таблицы, обращаясь к коду, и выполним финальную сортировку.

// Шаг 1: Подготовка данных во временной таблице
ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет КАК Счет,
    СУММА(ХозрасчетныйОстатки.СуммаОстатокДт) КАК Сумма
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки КАК ХозрасчетныйОстатки
СГРУППИРОВАТЬ ПО
    ХозрасчетныйОстатки.Счет;

// Шаг 2: Итоговая выборка с сортировкой
ВЫБРАТЬ
    ВТ_Остатки.Счет.Код КАК КодСчета,
    ВТ_Остатки.Сумма КАК Сумма
ИЗ
    ВТ_Остатки КАК ВТ_Остатки
УПОРЯДОЧИТЬ ПО
    ВТ_Остатки.Счет.Код

В данном случае на втором этапе группировка уже не используется, поэтому УПОРЯДОЧИТЬ ПО не вступает в конфликт с СГРУППИРОВАТЬ ПО. Платформа спокойно выполнит неявное соединение с планом счетов для получения кода и корректной сортировки.

Практические советы и рекомендации

Подводя итог, проанализируем основные правила работы с группировками в запросах 1С:

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

← На главную