Как правильно упорядочить данные в дереве значений при наличии дублей в запросе 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке отчетов и обработок, использующих деревья значений, разработчики часто сталкиваются с проблемой задвоения записей при выполнении левых соединений в запросе. Это приводит к тому, что агрегатные данные (остатки, суммы) суммируются неверно, а сортировка строк сбивается. Рассмотрим, как системно подойти к решению этой задачи и добиться корректного вывода данных.

Анализ причин возникновения дублей

Основная причина появления дублей кроется в архитектуре запроса. Когда мы присоединяем к основной таблице (например, к регистру Спецификация) другие таблицы, в которых по одному ключу (номенклатуре или регистратору) содержится несколько записей, система автоматически создает декартово произведение, дублируя строки основной выборки. Использование РАЗЛИЧНЫЕ часто «лечит» визуальную составляющую, но при этом нарушает логику нумерации строк и затрудняет дальнейшую обработку данных.

Метод решения через временные таблицы

Наиболее надежный способ борьбы с дублями и одновременно — с проблемой сортировки, это использование пакетов запросов с временными таблицами. Мы разбиваем процесс на два этапа:

  1. Сначала формируем временную таблицу уникальных записей, которая станет «скелетом» нашего отчета.
  2. Затем выполняем соединения с остальными данными уже по уникальному ключу, полученному на первом этапе.

Рассмотрим пример реализации такой структуры:


ВЫБРАТЬ 
    Спецификация.Регистратор, 
    Спецификация.Номенклатура, 
    Спецификация.Проект, 
    Спецификация.ЗаявкаНаКомплектацию КАК ДокументЗаявки, 
    МИНИМУМ(Спецификация.НомерСтроки) КАК НомерСтроки 
ПОМЕСТИТЬ тСпецификация 
ИЗ РегистрНакопления.Спецификация КАК Спецификация 
СГРУППИРОВАТЬ ПО 
    Спецификация.Регистратор, 
    Спецификация.Номенклатура, 
    Спецификация.Проект, 
    Спецификация.ЗаявкаНаКомплектацию;

После того как данные помещены во временную таблицу тСпецификация, мы можем смело присоединять остатки и другие данные, не опасаясь, что количество строк увеличится сверх меры.

Оптимизация виртуальных таблиц

При использовании виртуальных таблиц, таких как Спецификация.Остатки, важно ограничивать выборку. Обращение к виртуальной таблице без фильтрации по номенклатуре приводит к перебору всего регистра, что замедляет работу системы. Мы можем передать список номенклатур из нашей временной таблицы прямо в условия виртуальной таблицы:


ВЫБРАТЬ 
    тСпец.Регистратор, 
    СУММА(ЕСТЬNULL(СпецОстатки.КоличествоОстаток, 0)) КАК ОстатокЗаявки
ИЗ тСпецификация КАК тСпец 
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Спецификация.Остатки(
    , 
    Номенклатура В (ВЫБРАТЬ т.Номенклатура ИЗ тСпецификация КАК т)
) КАК СпецОстатки 
ПО тСпец.Номенклатура = СпецОстатки.Номенклатура 
И тСпец.Регистратор = СпецОстатки.ЗаявкаНаКомплектацию
СГРУППИРОВАТЬ ПО тСпец.Регистратор

Как сохранить порядок строк как в документе

Чтобы дерево значений в точности повторяло порядок строк в исходном документе, необходимо:

При выводе результата в дерево, используйте метод Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам). Это позволит платформе автоматически распределить записи по иерархическим уровням, сохраняя заданную нами сортировку внутри каждого уровня.

Почему следует избегать запросов в циклах

Использование Запрос.Выполнить() внутри цикла обхода дерева — это критическая ошибка проектирования. Каждый вызов запроса к базе данных создает нагрузку на сервер. Вместо этого:

  1. Соберите все данные одним или несколькими пакетами запросов до начала цикла.
  2. Поместите результат в ТаблицаЗначений.
  3. Для обработки дерева используйте методы поиска НайтиСтроки() или Найти() по коллекции строк в памяти.

Если вы следуете этим рекомендациям, вы сможете избавиться от «танцев с бубном» при группировке данных и обеспечите стабильную, быструю работу вашего отчета, при этом полностью сохранив читаемость структуры документа в дереве значений.

← На главную