При разработке интерфейсов на платформе 1С:Предприятие 8 программисты часто сталкиваются с нестандартным поведением динамических списков. Одной из таких проблем является «схлопывание» или исчезновение строк при попытке вывести один и тот же объект (например, документ) несколько раз с разными дополнительными данными. В этой статье мы подробно разберем, почему динамический список в 1С (особенно в конфигурациях на обычных формах, таких как УПП 1.3) может вести себя некорректно при использовании объединений и инструкции ПЕРВЫЕ.
Первое, на что стоит обратить внимание — это использование конструкции ВЫБРАТЬ ПЕРВЫЕ внутри текста запроса динамического списка. Рассмотрим ситуацию: разработчик хочет получить по одной записи из разных источников для одного документа и использует ОБЪЕДИНИТЬ ВСЕ. Однако, согласно документации и практике, инструкция ПЕРВЫЕ на верхнем уровне запроса динамического списка либо игнорируется, либо приводит к непредсказуемым результатам.
Проанализируем механизм работы платформы. Когда мы открываем форму со списком, система не выполняет ваш запрос «как есть». Она оборачивает его в подзапрос, добавляет свои условия отбора, сортировки и, что самое важное, собственные ограничения количества записей (например, TOP 45) для обеспечения постраничного вывода. Наличие вашей инструкции ПЕРВЫЕ внутри этого механизма нарушает логику построения SQL-запроса. В режиме совместимости 8.2 использование ПЕРВЫЕ при указанной основной таблице вовсе запрещено платформой.
Решение: Если вам необходимо ограничить выборку внутри динамического списка, следует перенести логику ограничения во вложенный запрос или во временную таблицу (если версия платформы позволяет использовать их в ДС). Но в большинстве случаев для динамического списка использование ПЕРВЫЕ является избыточным и вредным.
Вторая и самая важная проблема заключается в том, как динамический список идентифицирует строки. Каждая строка в списке должна иметь уникальный ключ. Рассмотрим ситуацию автора темы: он хочет вывести документ РеализацияТоваровУслуг дважды — один раз с данными по счету-фактуре, второй раз с данными по ТОРГ-12.
Если в настройках динамического списка указана «Основная таблица» (например, Документ.РеализацияТоваровУслуг), то в качестве ключа строки платформа всегда будет использовать ссылку на документ. Когда ваш запрос возвращает две строки с одинаковой ссылкой, динамический список считает их одной и той же записью. В результате:
Для того чтобы динамический список корректно отображал несколько строк для одного и того же документа, нам необходимо выполнить два условия: убрать основную таблицу и сформировать составной уникальный ключ. Рассмотрим этот процесс по шагам.
Шаг 1. Отказ от основной таблицы. В свойствах динамического списка в конфигураторе необходимо очистить поле «Основная таблица». Это переведет список в режим работы с произвольным запросом без жесткой привязки к метаданным одного объекта.
Шаг 2. Формирование уникального ключа в запросе. Нам нужно создать поле, которое будет уникальным для каждой строки в объединении. Давайте посмотрим на пример запроса, который решает эту задачу:
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
"СчетФактура" КАК ВидДокумента,
Реализация.Ссылка.УникальныйИдентификатор() + "СФ" КАК КлючСтроки,
... данные по СФ ...
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Реализация.Ссылка,
"ТОРГ12",
Реализация.Ссылка.УникальныйИдентификатор() + "Т12",
... данные по ТОРГ-12 ...
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
Шаг 3. Настройка ключа в конфигураторе. После изменения запроса необходимо зайти в «Настройку списка» и в списке полей найти наше новое поле КлючСтроки. В колонке «Использовать как ключ» нужно установить флажок. Теперь платформа будет понимать, что это разные записи, несмотря на то, что ссылка на документ в них совпадает.
Использование ОБЪЕДИНИТЬ ВСЕ в динамических списках (особенно в УПП на больших объемах данных) — это тяжелая операция. Когда мы убираем основную таблицу, мы лишаем платформу возможности эффективно использовать индексы для стандартных отборов. Система будет вынуждена выполнять объединение больших таблиц перед тем, как наложить фильтры.
Чтобы минимизировать нагрузку, рекомендуется:
СрезПоследних) через точку от ссылок в основном запросе. Лучше соединяться с ними по индексу.Автор темы упомянул, что «сломал базу», пытаясь изменить режим совместимости. Важно помнить, что в старых конфигурациях (УПП, ЗУП 2.5, КА 1.1) многие механизмы жестко завязаны на поведение платформы версии 8.2. Изменение режима совместимости меняет логику работы блокировок и трансляции запросов. Если вам нужно решить задачу в рамках 8.2.16, придерживайтесь следующих правил:
РАЗЛИЧНЫЕ и ПЕРВЫЕ в запросах динамических списков, если хотите стабильной работы.ОБЪЕДИНИТЬ ВСЕ вместо ОБЪЕДИНИТЬ, так как обычное объединение выполняет дополнительную операцию поиска дублей, что крайне медленно и часто бессмысленно для ДС.Соблюдение этих рекомендаций позволит вам создавать сложные и функциональные динамические списки, которые будут работать предсказуемо и быстро даже в устаревших программных средах.