Как реализовать отбор дублей в отчете СКД по транспортному средству и пассажиру

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

В процессе разработки отчетов в системе компоновки данных (СКД), особенно для отраслевых решений вроде «Управление автотранспортом» (УАТ), часто возникает задача поиска ошибочных или избыточных данных. Одной из таких задач является выявление «дублей» — ситуаций, когда на одно и то же ТранспортноеСредство или на одного Пассажира выписано несколько документов (например, уатПутевойЛист) в течение одного дня. Рассмотрим подробно, как реализовать такой механизм с использованием параметров-флагов («галочек») непосредственно в запросе СКД.

Постановка задачи и анализ исходных данных

Представим ситуацию: у нас есть стандартный запрос, выбирающий данные из таблицы документов. Нам необходимо добавить в настройки отчета два параметра типа Булево: ТолькоДублиАвтомобилей и ТолькоДублиПассажиров. При установке этих флагов отчет должен выводить не все записи, а только те, которые имеют повторения по соответствующей аналитике в рамках одного календарного дня. Проанализируем структуру основного запроса, с которым мы будем работать:


ВЫБРАТЬ
    уатПутевойЛист.Ссылка КАК Ссылка,
    уатПутевойЛист.Дата КАК Дата,
    уатПутевойЛист.ТранспортноеСредство КАК ТранспортноеСредство,
    уатПутевойЛист.Пассажир КАК Пассажир,
    уатПутевойЛист.Водитель1 КАК Водитель1
ИЗ
    Документ.уатПутевойЛист КАК уатПутевойЛист
ГДЕ
    уатПутевойЛист.Дата МЕЖДУ &ДатаН И &ДатаК
    И уатПутевойЛист.Рассчитан = ИСТИНА

Способ 1: Использование коррелированного подзапроса в условии ГДЕ

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

Для того чтобы отобрать дубли по транспортному средству, нам нужно убедиться, что в базе существует более одной записи с таким же ТранспортноеСредство в тот же день (НАЧАЛОПЕРИОДА(Дата, ДЕНЬ)). Рассмотрим пример реализации такого условия:


И (НЕ &ТолькоДублиАвтомобилей 
    ИЛИ уатПутевойЛист.ТранспортноеСредство В (
        ВЫБРАТЬ
            Т.ТранспортноеСредство
        ИЗ
            Документ.уатПутевойЛист КАК Т
        ГДЕ
            Т.Дата МЕЖДУ &ДатаН И &ДатаК
            И Т.Рассчитан = ИСТИНА
        СГРУППИРОВАТЬ ПО
            Т.ТранспортноеСредство,
            НАЧАЛОПЕРИОДА(Т.Дата, ДЕНЬ)
        ИМЕЮЩИЕ
            КОЛИЧЕСТВО(Т.Ссылка) > 1
    )
)

В данном коде мы используем оператор ИЛИ в связке с параметром. Если галочка ТолькоДублиАвтомобилей не установлена (значение Ложь), то выражение НЕ &ТолькоДублиАвтомобилей становится Истиной, и все условие выполняется для каждой строки. Если же галочка установлена, в действие вступает вторая часть условия — проверка вхождения ТС в список задублированных.

Способ 2: Оптимизированный поиск дублей через проверку существования

Для повышения производительности на больших объемах данных (например, когда количество путевых листов превышает десятки тысяч) лучше использовать оператор ВЫБРАТЬ 1 и СУЩЕСТВУЕТ. Проанализируем, как можно переписать условие для пассажиров:


И (НЕ &ТолькоДублиПассажиров 
    ИЛИ 1 В (
        ВЫБРАТЬ ПЕРВЫЕ 1
            1
        ИЗ
            Документ.уатПутевойЛист КАК Т_Дубль
        ГДЕ
            Т_Дубль.Пассажир = уатПутевойЛист.Пассажир
            И НАЧАЛОПЕРИОДА(Т_Дубль.Дата, ДЕНЬ) = НАЧАЛОПЕРИОДА(уатПутевойЛист.Дата, ДЕНЬ)
            И Т_Дубль.Ссылка <> уатПутевойЛист.Ссылка
            И Т_Дубль.Рассчитан = ИСТИНА
    )
)

Важный нюанс: Обратите внимание на условие Т_Дубль.Ссылка <> уатПутевойЛист.Ссылка. Оно необходимо для того, чтобы подзапрос не нашел сам себя. Мы ищем любую другую запись, отличную от текущей, но с тем же пассажиром и той же датой.

Оптимизация производительности: Использование временных таблиц

Если отчет формируется слишком медленно, рекомендуется отказаться от подзапросов в секции ГДЕ и перейти к использованию пакета запросов с временными таблицами. Рассмотрим, как это сделать структурно:

  1. Первый запрос пакета: Выбираем все комбинации аналитик (ТС или Пассажир) и дат, где количество записей больше единицы. Результат помещаем во временную таблицу ВТ_Дубли.
  2. Второй запрос пакета: Выбираем основные данные документов и соединяем их (ЛЕВОЕ СОЕДИНЕНИЕ) с ВТ_Дубли.
  3. Настройка СКД: В самой схеме компоновки данных используем отбор по полю из временной таблицы (например, если поле Количество из ВТ_Дубли не заполнено, значит запись не является дублем).

Пример запроса для получения временной таблицы дублей:


ВЫБРАТЬ
    уатПутевойЛист.ТранспортноеСредство КАК ТранспортноеСредство,
    НАЧАЛОПЕРИОДА(уатПутевойЛист.Дата, ДЕНЬ) КАК ПериодДень
ПОМЕСТИТЬ ВТ_ДублиАвто
ИЗ
    Документ.уатПутевойЛист КАК уатПутевойЛист
ГДЕ
    уатПутевойЛист.Дата МЕЖДУ &ДатаН И &ДатаК
СГРУППИРОВАТЬ ПО
    уатПутевойЛист.ТранспортноеСредство,
    НАЧАЛОПЕРИОДА(уатПутевойЛист.Дата, ДЕНЬ)
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(уатПутевойЛист.Ссылка) > 1
;

Тонкости настройки СКД и визуализация

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

Также стоит учитывать специфику уатПутевойЛист. В некоторых случаях дублем считается не совпадение календарного дня, а реальное пересечение временных интервалов работы. Если бизнес-логика требует именно такого подхода, в подзапросе следует сравнивать периоды: Т_Дубль.ДатаВыезда < уатПутевойЛист.ДатаВозвращения И Т_Дубль.ДатаВозвращения > уатПутевойЛист.ДатаВыезда. Это позволит найти путевые листы, которые физически «накладываются» друг на друга по времени работы одного автомобиля.

Подводя итог, отметим, что выбор метода (простой подзапрос или временные таблицы) зависит от предполагаемого объема данных. Для оперативного анализа за небольшой период (день или неделя) вполне достаточно решения с коррелированным подзапросом в ГДЕ, предложенного в обсуждении на форуме.

← На главную