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