Ошибка «В выборке должно быть указано хотя бы одно измерение или ресурс» в СКД: почему возникает и как исправить?

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

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда запрос, прекрасно работающий в консоли запросов, выдает ошибку в самом отчете. Одна из самых коварных ошибок — «В выборке должно быть указано хотя бы одно измерение или ресурс». Особенно странно это выглядит, когда мы просто меняем состав выбранных полей в настройках отчета. Давайте подробно разберем, почему это происходит и как правильно настроить схему компоновки, чтобы отчет работал стабильно.

Разбор исходной ситуации

Рассмотрим пример запроса, который вызывает проблему. В нем используется временная таблица для получения базы распределения (например, общей суммы доходов), которая затем соединяется с основной таблицей оборотов для расчета долей или распределения сумм.


ВЫБРАТЬ
    ДвиженияДенежныеСредстваКонтрагентОбороты.СуммаОплатыОборот КАК Сумма
ПОМЕСТИТЬ БазаРаспределения1
ИЗ
    РегистрНакопления.ДвиженияДенежныеСредстваКонтрагент.Обороты(&НачПериода, &КонПериода, Авто, ...) КАК ДвиженияДенежныеСредстваКонтрагентОбороты;

///////////////////////////////////////////////////////////

ВЫБРАТЬ
    ДвиженияДенежныеСредстваКонтрагентОбороты.СтатьяДвиженияДенежныхСредств КАК СтатьяДДС,
    ДвиженияДенежныеСредстваКонтрагентОбороты.Подразделение КАК Подразделение,
    СУММА(ДвиженияДенежныеСредстваКонтрагентОбороты.СуммаОплатыОборот) КАК СуммаВсего,
    СУММА(БазаРаспределения1.Сумма) КАК Сумма
ИЗ
    РегистрНакопления.ДвиженияДенежныеСредстваКонтрагент.Обороты(...) КАК ДвиженияДенежныеСредстваКонтрагентОбороты
    ЛЕВОЕ СОЕДИНЕНИЕ БазаРаспределения1 КАК БазаРаспределения1
    ПО (ИСТИНА)
СГРУППИРОВАТЬ ПО
    ДвиженияДенежныеСредстваКонтрагентОбороты.СтатьяДвиженияДенежныхСредств,
    ДвиженияДенежныеСредстваКонтрагентОбороты.Подразделение

Проблема проявляется так: когда в пользовательских настройках на закладке «Выбранные поля» включено поле Сумма, отчет формируется. Как только мы его убираем — получаем ошибку. Проанализируем причину такого поведения.

Выясняем причину: как работает оптимизатор СКД

Система компоновки данных не отправляет ваш запрос в СУБД «как есть». Она выполняет трансформацию текста запроса, исходя из текущих настроек отчета (группировок, отборов, выбранных полей). Этот процесс называется интеллектуальной оптимизацией.

Разберем логику оптимизатора по шагам:

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

Решение №1: Использование флага «Обязательное» в ролях полей

Это самый быстрый и эффективный способ решения проблемы, когда логика вашего отчета завязана на соединениях, которые нельзя разрывать. Нам нужно принудительно запретить оптимизатору удалять поле из запроса.

Рассмотрим алгоритм действий:

  1. Откройте схему компоновки данных и перейдите на закладку «Наборы данных».
  2. Найдите ваше поле (в нашем примере это Сумма из временной таблицы).
  3. В колонке «Роль» нажмите на кнопку выбора.
  4. В открывшемся окне установите флажок «Обязательное».

Что это дает? Установка этого флага сообщает СКД: «Это поле должно присутствовать в итоговом SQL-запросе всегда, даже если пользователь не вывел его в отчет». В результате соединение с временной таблицей сохранится, и структура запроса не нарушится.

Решение №2: Использование функции «ВычислитьВыражение»

Зачастую соединение ПО ИСТИНА (декартово произведение) используется для получения общего итога во всех строках отчета. Это ресурсоемкая операция. Проанализируем альтернативный подход с использованием возможностей самого процессора компоновки.

Вместо того чтобы тянуть общую сумму через соединение в запросе, мы можем рассчитать её на уровне ресурсов СКД. Для этого:

  1. Удалите временную таблицу и соединение из основного запроса.
  2. На закладке «Ресурсы» добавьте новое поле.
  3. В выражении ресурса используйте функцию: Сумма(ВычислитьВыражение("СуммаОплатыОборот", , "ОбщийИтог")).

Этот метод работает быстрее, так как платформа вычисляет итог один раз и «раздает» его во все строки без выполнения тяжелых SQL-соединений.

Решение №3: Изменение алиасов (псевдонимов) полей

Иногда оптимизатор СКД ошибочно сопоставляет поля с одинаковыми именами из разных таблиц. Посмотрим, как это исправить. Если в первой временной таблице поле называется Сумма, и в основном запросе есть поле Сумма, компоновщик может запутаться при исключении полей.

Попробуйте дать уникальные имена полям во временных таблицах, например:


ВЫБРАТЬ
    СуммаОплатыОборот КАК СуммаДляРаспределения
ПОМЕСТИТЬ БазаРаспределения1
...

Хотя этот способ помогает не всегда, он является хорошим тоном при написании сложных запросов в СКД, так как снижает вероятность неоднозначной трактовки полей оптимизатором.

Важные нюансы работы с соединением «ПО ИСТИНА»

Проанализируем риски, которые несет в себе конструкция ЛЕВОЕ СОЕДИНЕНИЕ ... ПО (ИСТИНА) в СКД:

Итоги

Мы выяснили, что ошибка «В выборке должно быть указано хотя бы одно измерение или ресурс» — это результат чрезмерной «заботы» оптимизатора СКД о производительности. Чтобы победить её, мы рассмотрели три способа:

  1. Установка флага «Обязательное» в роли поля (самый надежный способ сохранить структуру запроса).
  2. Использование функции ВычислитьВыражение в ресурсах (лучший способ с точки зрения производительности).
  3. Корректировка псевдонимов полей для предотвращения коллизий.

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

← На главную