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