Как сгруппировать данные и соединить типы документов со строковым полем в запросе СКД?

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

При разработке отчетов в Системе компоновки данных (СКД) разработчики часто сталкиваются с задачей объединения или сравнения данных из информационной базы с данными из внешних файлов (например, Excel или XML). Распространенный сценарий — попытка сгруппировать данные по типу документа или соединить поле типа Тип с текстовым названием документа из загруженной таблицы значений.

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

Выясним причину: почему функция ПРЕДСТАВЛЕНИЕ не работает в группировках

Проанализируем механику работы языка запросов 1С на уровне СУБД:

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

Ниже рассмотрим проверенные и правильные варианты решения этой задачи.

Способ 1. Преобразование строки в тип 1С до передачи таблицы в запрос (Рекомендуемый подход)

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

Рассмотрим пример реализации на языке 1С:


// Создаем или дополняем Таблицу Значений колонкой с ссылочным типом
ТЗ.Колонки.Добавить("ТипДокументаСсылка");

Для Каждого Стр Из ТЗ Цикл
    ИмяДок = Стр.ТипДокумента; // Например, "ПриходныйОрдерНаТовары"
    Если Метаданные.Документы.Найти(ИмяДок) <> Неопределено Тогда
        Стр.ТипДокументаСсылка = Документы[ИмяДок].ПустаяСсылка();
    КонецЕсли;
КонецЦикла;

После заполнения колонки ТипДокументаСсылка мы передаем эту таблицу в запрос или в Набор данных - Объект СКД. Теперь в самом запросе можно легко выполнить связывание и группировку по типам документов:


ВЫБРАТЬ
    ТЗ.ТипДокументаСсылка КАК ТипДокумента,
    СУММА(ТЗ.КоличествоФайл) КАК КоличествоФайл
ПОМЕСТИТЬ ВТ_Файл
ИЗ
    &ТЗ КАК ТЗ
СГРУППИРОВАТЬ ПО
    ТЗ.ТипДокументаСсылка;

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

При таком подходе соединение наборов данных будет происходить по типам или ссылкам, что выполняется СУБД максимально быстро.

Способ 2. Использование конструкции ВЫБОР КОГДА ... ССЫЛКА в запросе

Если изменить исходную таблицу данных невозможно, мы можем в тексте запроса явным образом сопоставить ссылки с их текстовыми наименованиями с помощью конструкции ВЫБОР КОГДА ... ССЫЛКА.

Посмотрим на пример применения конструкции в запросе:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ТоварыНаСкладах.Регистратор ССЫЛКА Документ.ПриходныйОрдерНаТовары 
            ТОГДА "ПриходныйОрдерНаТовары"
        КОГДА ТоварыНаСкладах.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг 
            ТОГДА "РеализацияТоваровУслуг"
        ИНАЧЕ "Прочее"
    КОНЕЦ КАК ТипДокумента,
    ТоварыНаСкладах.Количество КАК Количество
ПОМЕСТИТЬ ВТ_ДанныеРегистра
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах;

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

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

Способ 3. Использование вычисляемых полей и функций общих модулей в СКД

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

Проанализируем пошагово настройку этой схемы:

  1. В запросе набора данных СКД выбираем сам регистратор без попыток преобразовать его в строку:
    
    ВЫБРАТЬ
        ТоварыНаСкладах.Регистратор КАК Регистратор,
        ТоварыНаСкладах.Количество КАК Количество
    ИЗ
        РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
    
  2. В конфигураторе создаем клиент-серверный общий модуль (например, РаботаСДетализациейСКД) и добавляем функцию с повторным использованием значений:
    
    Функция ПолучитьИмяТипаДокумента(СсылкаНаДокумент) Экспорт
        Если НЕ ЗначениеЗаполнено(СсылкаНаДокумент) Тогда
            Возврат "";
        КонецЕсли;
        Возврат СсылкаНаДокумент.Метаданные().Имя;
    КонецФункции
    
  3. В схеме компоновки данных переходим на вкладку Вычисляемые поля и добавляем новое поле с выражением: РаботаСДетализациейСКД.ПолучитьИмяТипаДокумента(Регистратор).
  4. На вкладке Настройки используем сформированное вычисляемое поле в качестве группировки. СКД автоматически выполнит вычисление строк и сгруппирует результат.

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

← На главную