В практике разработки на платформе 1С часто возникает задача преобразования данных из вертикального вида (строки) в горизонтальный (колонки). Типичный пример — вывод характеристик номенклатуры, дополнительных сведений или результатов замеров, где каждое новое свойство хранится в отдельной строке, а в отчете их нужно выстроить в ряд для каждого объекта. Рассмотрим подробнее, как решить эту задачу различными методами, проанализируем их эффективность и разберем конкретные примеры кода.
Этот метод считается наиболее оптимальным с точки зрения производительности SQL-сервера. Суть заключается в том, что мы выбираем все данные одним списком, а затем «разбрасываем» их по колонкам с помощью конструкции ВЫБОР, используя группировку по ключевому полю. Рассмотрим этот подход на примере получения значений П1, П2 и П3 для объекта К1.
Проанализируем пример запроса:
ВЫБРАТЬ
ТаблицаДанных.Объект КАК Объект,
МАКСИМУМ(ВЫБОР
КОГДА ТаблицаДанных.Свойство = "П1"
ТОГДА ТаблицаДанных.Значение
ИНАЧЕ NULL
КОНЕЦ) КАК ПолеП1,
МАКСИМУМ(ВЫБОР
КОГДА ТаблицаДанных.Свойство = "П2"
ТОГДА ТаблицаДанных.Значение
ИНАЧЕ NULL
КОНЕЦ) КАК ПолеП2,
МАКСИМУМ(ВЫБОР
КОГДА ТаблицаДанных.Свойство = "П3"
ТОГДА ТаблицаДанных.Значение
ИНАЧЕ NULL
КОНЕЦ) КАК ПолеП3
ИЗ
ВременнаяТаблицаДанных КАК ТаблицаДанных
СГРУППИРОВАТЬ ПО
ТаблицаДанных.Объект
Почему это работает: функция МАКСИМУМ (или МИНИМУМ) игнорирует значения NULL. В результате для каждой группы по объекту в конкретную колонку попадет только то значение, которое соответствует условию ВЫБОР, а все остальные строки превратятся в NULL и будут отброшены агрегатной функцией.
Этот способ требует всего одного сканирования таблицы, что делает его предпочтительным при работе с большими объемами данных.
Если количество колонок заранее известно и оно невелико (например, не более 5-10), можно использовать последовательное соединение таблиц. Рассмотрим ситуацию, когда нам нужно собрать данные из разных источников или по разным фильтрам в одну строку.
Разберем пример кода:
ВЫБРАТЬ
ВТ_Объекты.Ссылка КАК Объект,
ЕСТЬNULL(ВТ_Данные1.Значение, 0) КАК Значение1,
ЕСТЬNULL(ВТ_Данные2.Значение, 0) КАК Значение2
ИЗ
ВТ_Объекты КАК ВТ_Объекты
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Данные1 КАК ВТ_Данные1
ПО ВТ_Объекты.Ссылка = ВТ_Данные1.Объект
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Данные2 КАК ВТ_Данные2
ПО ВТ_Объекты.Ссылка = ВТ_Данные2.Объект
Важные нюансы при использовании соединений:
Ссылка или Объект). Без этого SQL-сервер будет выполнять ресурсоемкое сканирование всей таблицы для каждого соединения.ЕСТЬNULL, чтобы избежать пустых значений в итоговом результате, особенно если планируются дальнейшие математические операции.Если задача стоит в выводе отчета пользователю, то самым эффективным решением будет использование встроенного механизма "Таблица" в СКД. Это позволяет не писать сложные запросы с транспонированием вручную.
Выполним следующие шаги для настройки:
Объект, ИмяСвойства, Значение.Объект.ИмяСвойства.Значение.Система автоматически развернет все имеющиеся в базе свойства в колонки и сгруппирует значения по строкам. Это самый гибкий метод, так как количество колонок будет меняться динамически в зависимости от состава данных в базе.
Иногда количество колонок неизвестно заранее, а результат нужно получить именно в коде (например, для выгрузки в Таблицу Значений), а не в отчете. В этом случае проанализируем подход с динамическим формированием текста запроса на языке 1С.
Рассмотрим алгоритм действий:
ВЫБРАТЬ.Пример программного формирования кода:
ТекстВыбора = "";
Для Каждого СтрокаСвойство Из ТаблицаСвойств Цикл
ТекстВыбора = ТекстВыбора +
", МАКСИМУМ(ВЫБОР КОГДА Свойство = &Свойство" + СтрокаСвойство.Номер +
" ТОГДА Значение ИНАЧЕ NULL КОНЕЦ) КАК " + СтрокаСвойство.ИмяБезПробелов;
Запрос.УстановитьПараметр("Свойство" + СтрокаСвойство.Номер, СтрокаСвойство.Ссылка);
КонецЦикла;
Запрос.Текст = "ВЫБРАТЬ Объект" + ТекстВыбора + " ИЗ ВТ_Данные СГРУППИРОВАТЬ ПО Объект";
Важное предостережение: при формировании условий ВЫБОР КОГДА старайтесь сравнивать ссылки (через параметры), а не строковые имена свойств через точку (например, Свойство.Наименование). Прямое обращение к реквизитам через точку в условии запроса (разыменование ссылки) приводит к неявному соединению таблиц на уровне СУБД, что замедляет выполнение в разы.
Выясним, какой метод лучше использовать в конкретной ситуации:
Рассмотренные приемы позволяют эффективно решать задачи по представлению данных в удобном для пользователя и системы виде. Помните о производительности и всегда проверяйте планы запросов при работе с большими объемами информации.