Как объединить данные в динамическом списке 1С без команды ОБЪЕДИНИТЬ

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

При разработке форм выбора и списков на управляемых формах 1С программисты часто сталкиваются с необходимостью вывести данные из нескольких источников или с разными условиями фильтрации в одном динамическом списке. Прямое использование конструкции ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ в произвольном запросе динамического списка может вызывать ошибки, особенно если в настройках списка заполнена Основная таблица или используются группировки.

Разберем подробно причины возникновения этой проблемы и рассмотрим эффективные варианты ее решения.

Почему возникают ошибки при использовании ОБЪЕДИНИТЬ в динамическом списке

Динамический список работает по принципу порционной выборки данных. Для корректного считывания, построения иерархии и настройки группировок системе компоновки данных (СКД) требуется четкая привязка к полю ключевой таблицы.

Проанализируем основные причины сбоев:

  1. Наличие основной таблицы: Если в свойствах динамического списка указана основная таблица (например, Справочник.Номенклатура), платформа рассчитывает на строгое соответствие строк исходной таблице. Конструкция ОБЪЕДИНИТЬ искажает порционное считывание, из-за чего система выдает ошибку.
  2. Использование группировок: При снятии свойства Основная таблица запрос с ОБЪЕДИНИТЬ может работать, однако при попытке сгруппировать данные динамический список теряет уникальные ключи и ломается.

Способ 1. Объединение условий через ИЛИ в одном запросе

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

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


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    СправочникНоменклатура.Ссылка КАК Ссылка,
    СправочникНоменклатура.Код КАК Код,
    СправочникНоменклатура.Наименование КАК Наименование,
    СправочникНоменклатура.Родитель КАК ProductGroup
ИЗ
    Справочник.Номенклатура КАК СправочникНоменклатура
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Цены.Номенклатура КАК Номенклатура
        ИЗ
            РегистрСведений.ЦеныПоставкиНоменклатуры.СрезПоследних(,
                УсловиеПоставки = &УсловиеПоставки
                И Валюта = &Валюта) КАК Цены
        ГДЕ
            НЕ Цены.ТипЗаписи = ЗНАЧЕНИЕ(Перечисление.ТипыЗаписей.Удаление)
        СГРУППИРОВАТЬ ПО
            Цены.Номенклатура
    ) КАК ЦеныНоменклатуры
    ПО СправочникНоменклатура.Ссылка = ЦеныНоменклатуры.Номенклатура
ГДЕ
    (НЕ ЦеныНоменклатуры.Номенклатура ЕСТЬ NULL
     И НЕ СправочникНоменклатура.Использование = ЗНАЧЕНИЕ(Перечисление.ИспользованиеНоменклатуры.Заблокирован))
    ИЛИ СправочникНоменклатура.Category = &Category

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

Способ 2. Соединение вложенного запроса с основной таблицей

Если логика получения данных требует сложных конструкций с объединением, мы можем обернуть объединение во вложенный запрос и связать его с основной таблицей через ВНУТРЕННЕЕ СОЕДИНЕНИЕ по ключевому полю Ссылка.

Посмотрим, как выглядит такой запрос:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    ВложенныйЗапрос.Код КАК Код,
    ВложенныйЗапрос.Наименование КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            СправочникНоменклатура.Ссылка КАК Ссылка,
            СправочникНоменклатура.Код КАК Код,
            СправочникНоменклатура.Наименование КАК Наименование
        ИЗ
            Справочник.Номенклатура КАК СправочникНоменклатура
        ГДЕ
            СправочникНоменклатура.Category = &Category

        ОБЪЕДИНИТЬ ВСЕ

        ВЫБРАТЬ
            СправочникНоменклатура.Ссылка КАК Ссылка,
            СправочникНоменклатура.Код КАК Код,
            СправочникНоменклатура.Наименование КАК Наименование
        ИЗ
            Справочник.Номенклатура КАК СправочникНоменклатура
        ГДЕ
            СправочникНоменклатура.Status = &Status
    ) КАК ВложенныйЗапрос
    ПО Номенклатура.Ссылка = ВложенныйЗапрос.Ссылка

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

Способ 3. Использование ПОЛНОГО СОЕДИНЕНИЯ и ЕСТЬNULL

Когда данные необходимо объединить из разрозненных таблиц или регистров, не связанных напрямую через одну сущность, альтернативой объединению служит ПОЛНОЕ СОЕДИНЕНИЕ с проверкой значений через функцию ЕСТЬNULL.

Проанализируем пример соединения двух независимых источников:


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

Архитектурные альтернативы для сложных случаев

Если ни один из вариантов в запросе динамического списка не подходит из-за падения производительности или специфических условий системы, рекомендуется использовать архитектурные решения платформы 1С:

  1. Журналы документов: Если требуется вывести в один динамический список документы разных видов, создайте объект метаданных Журнал документов. Список по журналу работает штатно с поддержкой всех группировок.
  2. Агрегирующий регистр сведений: Для сложных комбинированных данных из регистров и справочников создается вспомогательный регистр сведений. Данные в него подготавливаются фоновым заданием или при проведении документов, а динамический список строится напрямую по этому регистру.
  3. Обогащение данных в событии ПриПолученииДанныхНаСервере: В самом запросе динамического списка выбираются только базовые записи основной таблицы. Дополнительные сведения считываются пакетом в программном обработчике таблицы формы ПриПолученииДанныхНаСервере только для текущих видимых строк на экране.
← На главную