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