Как реализовать условную связь между наборами данных в СКД 1С?

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

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

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

Почему не работает условие связи через несколько строк

Проанализируем типичную ошибку. Разработчик добавляет две строки связей между таблицами Таблица1 (источник) и Таблица2 (приемник):

  1. Строка 1: Источник: Поле1, Приемник: Поле1, Условие связи: Поле3 = Истина
  2. Строка 2: Источник: Поле1, Приемник: Поле2, Условие связи: Поле3 = Ложь

Ожидается, что платформа применит логику ветвления (ИЛИ), однако в результате связь вообще не срабатывает. Выясним причину такого поведения платформы 1С:

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

Вариант 1. Объединение логики в один набор данных — запрос (Рекомендуемый)

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

Посмотрим на пример запроса:


ВЫБРАТЬ
    Табл1.Поле1 КАК Поле1,
    Табл1.Поле3 КАК Поле3,
    Табл2.Данные КАК Данные
ИЗ
    Таблица1 КАК Табл1
    ЛЕВОЕ СОЕДИНЕНИЕ Таблица2 КАК Табл2
        ПО (ВЫБОР
                КОГДА Табл1.Поле3 = ИСТИНА 
                    ТОГДА Табл2.Поле1
                ИНАЧЕ Табл2.Поле2
            КОНЕЦ = Табл1.Поле1)

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

Вариант 2. Передача параметров в подчиненный набор данных — запрос

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

Разберем по шагам, как настроить этот вариант:

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

Вариант 3. Подготовка синтетического ключа связи (для внешних наборов данных)

Если набор-приемник является таблицей значений (тип Набор данных - объект), использование параметров запроса невозможно. В таком случае необходимо заранее нормализовать данные и сформировать единое ключевое поле для связи.

Рассмотрим, как это реализовать:

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