Как в 1С:Предприятие найти транспортные средства, у которых отсутствует действующий полис ОСАГО?

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

В процессе разработки отчетов в системе 1С:Предприятие (особенно в отраслевых решениях, таких как «Управление автотранспортом»), часто возникает задача выявления объектов, для которых не заданы определенные параметры или отсутствуют записи в связанных регистрах. Типичный пример — поиск автомобилей (ТС), на которые не оформлен полис ОСАГО.

Рассмотрим ситуацию: у нас есть справочник уатТС (Транспортные средства) и регистр сведений уатДокументыТС, где хранятся записи обо всех документах (ПТС, ОСАГО, КАСКО и т.д.). Нам нужно получить список машин, у которых в этом регистре нет записи с видом документа «ОСАГО».

Разбор типичной ошибки при построении запроса

Проанализируем сначала неправильный подход, который часто выбирают начинающие разработчики. Если мы просто наложим условие в секции ГДЕ:


ГДЕ
    НЕ уатДокументыТС.ВидДокумента.Наименование = "ОСАГО"

Такой запрос не решит задачу. Он выведет все записи регистра по другим документам (например, ПТС или СТС), даже если у этого же автомобиля есть ОСАГО. В итоге автомобиль попадет в список несколько раз под видом «ТС без ОСАГО», что является логической ошибкой. Нам же нужно проверить именно отсутствие связи между объектом ТС и конкретным видом документа.

Способ №1: Использование Левого соединения с проверкой на NULL

Это классический и наиболее производительный метод в языке запросов 1С. Разберем его по шагам. Основная идея заключается в том, чтобы соединить таблицу всех автомобилей с таблицей документов по условию соответствия ТС и фильтру по виду документа прямо в условии связи.

Рассмотрим пример кода:


ВЫБРАТЬ
    СпрТС.Ссылка КАК ТС
ИЗ
    Справочник.уатТС КАК СпрТС
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.уатДокументыТС КАК РегДокументы
        ПО СпрТС.Ссылка = РегДокументы.ТС
            И РегДокументы.ВидДокумента.Код = "000000001" // Предположим, это код ОСАГО
ГДЕ
    РегДокументы.ТС ЕСТЬ NULL
    И НЕ СпрТС.ПометкаУдаления
    И СпрТС.ДатаВыбытия = ДАТАВРЕМЯ(1, 1, 1)

Проанализируем, почему это работает:

  1. Мы берем все активные ТС из справочника.
  2. Присоединяем к ним записи из регистра, но только те, где вид документа соответствует «ОСАГО».
  3. Если для конкретной машины в регистре нет записи «ОСАГО», то поля присоединенной таблицы РегДокументы заполнятся значением NULL.
  4. В секции ГДЕ мы оставляем только те строки, где РегДокументы.ТС ЕСТЬ NULL, тем самым отсеивая машины, у которых документ найден.

Способ №2: Использование временных таблиц (ВТ)

Выясним, как реализовать ту же задачу более структурно, что особенно полезно при сложных условиях (например, когда нужно учитывать архивные записи). Этот метод часто более нагляден для отладки.

Сначала выберем все ТС, у которых есть ОСАГО, во временную таблицу:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    уатДокументыТС.ТС КАК ТС
ПОМЕСТИТЬ вт_ЕстьОСАГО
ИЗ
    РегистрСведений.уатДокументыТС КАК уатДокументыТС
ГДЕ
    уатДокументыТС.ВидДокумента.Код = "000000001"
    И НЕ уатДокументыТС.Архив // Проверяем, что документ не в архиве
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпрТС.Ссылка КАК ТС
ИЗ
    Справочник.уатТС КАК СпрТС
ГДЕ
    СпрТС.Ссылка НЕ В (ВЫБРАТЬ ТС ИЗ вт_ЕстьОСАГО)
    И СпрТС.ДатаВыбытия = ДАТАВРЕМЯ(1, 1, 1)

Этот подход исключает дублирование строк и позволяет четко отделить логику «у кого документ есть» от логики «вывести всех остальных».

Учет специфики: архивные записи и сроки действия

В реальных базах (например, в УАТ) простого наличия записи в регистре уатДокументыТС недостаточно. Документ может существовать, но быть просроченным или находиться в архиве. Посмотрим на улучшенный запрос, который учитывает флаг Архив и дату окончания действия полиса.


ВЫБРАТЬ
    СпрТС.Ссылка КАК ТС
ИЗ
    Справочник.уатТС КАК СпрТС
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.уатДокументыТС КАК РегДокументы
        ПО СпрТС.Ссылка = РегДокументы.ТС
            И РегДокументы.ВидДокумента.Код = "000000001"
            И (НЕ РегДокументы.Архив)
            И РегДокументы.ДатаОкончания >= &ТекущаяДата
ГДЕ
    СпрТС.ДатаВыбытия = ДАТАВРЕМЯ(1, 1, 1)
    И РегДокументы.ТС ЕСТЬ NULL

Важный момент: если мы добавим условие по ДатаОкончания в секцию ГДЕ, запрос снова сломается (строки с NULL не пройдут сравнение с датой). Поэтому все условия, касающиеся свойств искомого документа, должны располагаться строго в блоке ПО левого соединения.

Реализация через Систему компоновки данных (СКД)

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

  1. Создадим Набор данных 1 (Запрос): ВЫБРАТЬ Ссылка ИЗ Справочник.уатТС.
  2. Создадим Набор данных 2 (Запрос): ВЫБРАТЬ ТС, ВидДокумента ИЗ РегистрСведений.уатДокументыТС ГДЕ ВидДокумента = &НужныйВид.
  3. На вкладке Связи наборов данных свяжем их по полю ТС. Важно: Набор 1 — источник, Набор 2 — приемник. Установите флаг «Обязательная связь» в значение Ложь.
  4. В настройках отчета (вкладка «Отбор») добавьте условие: НаборДанных2.ТС Не заполнено.

Такой метод позволяет пользователю в режиме 1С:Предприятие гибко управлять параметрами отчета, не меняя конфигурацию.

Рекомендации по оптимизации

При работе с большими автопарками (тысячи единиц техники) следует учитывать следующие рекомендации:

Таким образом, комбинируя механизмы левого соединения и правильную расстановку фильтров, мы получаем надежный инструмент для контроля наличия необходимых документов у объектов учета.

← На главную