Почему возникает ошибка при поиске в динамическом списке с агрегатными функциями и как ее решить

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

При разработке интерфейсов на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью вывода сложных данных в списках. Одной из распространенных задач является отображение информации из регистров накопления или сведений непосредственно в списке справочника. Для этого в динамическом списке (ДС) используется произвольный запрос с левым соединением. Однако такая структура может привести к неожиданным ошибкам при попытке стандартного поиска по списку. Рассмотрим, почему это происходит и как правильно настроить систему для корректной работы.

Суть проблемы и анализ ситуации

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

Проблема проявляется в тот момент, когда пользователь вводит текст в строку поиска. Платформа генерирует внутренний SQL-запрос, пытаясь найти совпадение во всех доступных колонках. Если колонка является ссылочной (например, тип Справочник.Сотрудники), 1С автоматически пытается выполнить поиск по представлению этой ссылки — то есть по полю Наименование.

Однако, если поле получено в результате работы функции МАКСИМУМ(Сотрудник), оно перестает быть простой ссылкой в глазах механизма поиска. Система пытается обратиться к атрибуту Наименование у результата агрегации, что вызывает технический сбой, так как СУБД не может корректно обработать такое обращение в конструкции WHERE или HAVING без дополнительных инструкций.

Разбор исходного запроса

Проанализируем пример запроса, который вызывает ошибку. В данном случае разработчик пытается получить данные об ИТ-объектах и привязать к ним сотрудника из регистра накопления:


ВЫБРАТЬ
    СправочникАА_ИТОбъекты.Ссылка КАК Ссылка,
    СправочникАА_ИТОбъекты.Код КАК Код,
    СправочникАА_ИТОбъекты.Наименование КАК Наименование,
    ВЫРАЗИТЬ(СправочникАА_ИТОбъекты.Описание КАК СТРОКА(250)) КАК Описание,
    СУММА(АА_ИТОбъектыИСотрудникиОстатки2.КоличествоОстаток) КАК ВсегоОстаток,
    МАКСИМУМ(ЕСТЬNULL(АА_ИТОбъектыИСотрудникиОстатки2.Сотрудник, ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка))) КАК Сотрудник
ИЗ
    Справочник.АА_ИТОбъекты КАК СправочникАА_ИТОбъекты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.АА_ИТОбъектыИСотрудники.Остатки КАК АА_ИТОбъектыИСотрудникиОстатки2
ПО АА_ИТОбъектыИСотрудникиОстатки2.ИТОбъект = СправочникАА_ИТОбъекты.Ссылка
СГРУППИРОВАТЬ ПО
    СправочникАА_ИТОбъекты.Ссылка,
    СправочникАА_ИТОбъекты.Код,
    СправочникАА_ИТОбъекты.Наименование

Обратим внимание на поле Сотрудник. Здесь используется связка МАКСИМУМ и ЕСТЬNULL. Именно эта конструкция становится «камнем преткновения» для стандартного поиска. Платформа «видит» тип данных как ссылку, но при попытке поиска по строке не может корректно сопоставить агрегированное значение с полем Наименование в таблице сотрудников.

Решение №1: Настройка ограничений в схеме компоновки данных

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

  1. Откроем редактор запроса динамического списка.
  2. Перейдем на вкладку «Настройки компоновки данных».
  3. В списке полей найдем наше поле Сотрудник.
  4. Проверим колонки «Ограничение условий» и «Ограничение поиска». Установим в них флажки.

Установка этих флагов сообщает платформе, что по данному полю (которое является результатом агрегации) не следует выполнять автоматическую фильтрацию или поиск. Это исключает генерацию некорректного SQL-кода, и ошибка пропадает. Пользователь сможет искать по наименованию объекта или коду, а проблемная колонка будет игнорироваться механизмом поиска.

Решение №2: Оптимизация структуры запроса (Рекомендуемое)

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

Рассмотрим более правильный подход — вынесение логики получения единственного сотрудника во вложенный запрос. Это позволит полю Сотрудник оставаться «чистым» ссылочным полем в основном запросе.

Проанализируем пример оптимизированного запроса:


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

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

Нюансы работы с «Ролями» полей

Выясним еще одну важную деталь: динамический список требует уникальности ключа (обычно это поле Ссылка). Если из-за соединений в списке появляются дубли по ссылке, система выдаст ошибку «Обнаружены дублирующиеся ключи».

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

Почему не работает полнотекстовый поиск?

Разберем ситуацию, если в списке включен режим Полнотекстовый поиск. Ошибка может возникать из-за того, что данные в регистре не индексируются механизмом полнотекстового поиска так же, как данные справочника. Когда система пытается найти строку «Иванов», она ищет ее в индексе. Но поле МАКСИМУМ(Сотрудник) отсутствует в индексе как строковое значение.

В этом случае платформа пытается переключиться на поиск через оператор ПОДОБНО, что в сочетании с GROUP BY приводит к существенному падению производительности или ошибке тайм-аута на больших таблицах. Поэтому ограничение условий поиска для агрегатных полей — это не просто способ убрать ошибку, но и метод оптимизации скорости работы формы.

Резюме

Для исправления ошибки при поиске в динамическом списке выполним следующие шаги:

  1. Проанализируем запрос на наличие агрегатных функций (СУММА, МАКСИМУМ, МИНИМУМ) над ссылочными полями.
  2. Если агрегация необходима, заходим в настройки компоновки данных динамического списка.
  3. Для проблемного поля устанавливаем «Ограничение условий» и «Ограничение поиска».
  4. В идеале — переносим группировку во вложенный запрос, чтобы сделать основной текст запроса максимально линейным и понятным для оптимизатора платформы 1С.

Эти действия позволят сохранить функциональность поиска по основным реквизитам справочника и обеспечат стабильную работу формы без вылетов и технических сообщений.

← На главную