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

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

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

Почему оператор В ИЕРАРХИИ не работает для документов

Начинающие разработчики часто пытаются применить конструкцию В ИЕРАРХИИ к документам, проводя аналогию со справочниками. Давайте проанализируем, почему это ошибочный путь. В платформе 1С оператор В ИЕРАРХИИ (IN HIERARCHY) предназначен для работы с объектами, имеющими встроенную иерархическую структуру «группа — элемент» или «элемент — элемент» (родительская связь). У документов такое свойство отсутствует на уровне ядра платформы.

Важно понимать: связь между документами в 1С обычно строится через реквизит типа «Ссылка», который разработчики часто называют ДокументОснование. Это логическая связь, а не физическая иерархия таблиц. Поэтому попытка выполнить запрос ГДЕ Ссылка В ИЕРАРХИИ (&ДокументСсылка) не вернет подчиненные документы, так как платформа не увидит в них наследников указанного объекта.

Использование критериев отбора в запросах

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

Для обращения к этим данным в языке запросов используется специальная виртуальная таблица. Разберем пример синтаксиса:


ВЫБРАТЬ
    СвязанныеДокументы.Ссылка КАК Документ
ИЗ
    КритерийОтбора.СвязанныеДокументы(&Основание) КАК СвязанныеДокументы

В данном случае в качестве параметра &Основание мы передаем ссылку на родительский документ. Платформа сама проанализирует все объекты, указанные в составе критерия отбора, и вернет те, которые ссылаются на наше &Основание.

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

СписокДокументов = КритерииОтбора.СвязанныеДокументы.Найти(ИскомыйДокумент);

Как найти подчиненные документы в самописной конфигурации

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

Способ 1: Прямой запрос к известным таблицам. Если мы точно знаем, какие типы документов могут быть подчинены, мы используем ОБЪЕДИНИТЬ ВСЕ:


ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг ГДЕ ДокументОснование = &Основание
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Ссылка ИЗ Документ.СчетФактураВыданный ГДЕ ДокументОснование = &Основание

Способ 2: Универсальный поиск через метаданные. Если видов документов много, мы можем программно перебрать метаданные и построить динамический запрос. Нам нужно проверить каждый документ на наличие реквизита, тип которого совпадает с типом нашего документа-основания. Обратите внимание, что реквизит может находиться как в шапке, так и в табличной части.

Поиск дублей через агрегатные функции: секция ИМЕЮЩИЕ

Перейдем ко второй части вопроса — поиску дублей среди найденных документов. Часто разработчики совершают ошибку, пытаясь использовать условие СУММА(1) > 1 или КОЛИЧЕСТВО(*) > 1 в секции ГДЕ. Выясним причину, почему это не работает.

В языке SQL и языке запросов 1С секция ГДЕ (WHERE) фильтрует строки до того, как будет выполнена группировка и расчет агрегатных функций. Для фильтрации уже сгруппированных данных (результатов функций СУММА, КОЛИЧЕСТВО и т.д.) предназначена специальная секция ИМЕЮЩИЕ (HAVING).

Рассмотрим пошагово алгоритм поиска дублей по номеру и дате в таблице документов:

  1. Выбираем поля: Указываем поля, по которым мы определяем уникальность (например, Номер и Дата).
  2. Считаем количество: Добавляем поле КОЛИЧЕСТВО(Ссылка) или просто КОЛИЧЕСТВО(*).
  3. Группируем: Обязательно используем СГРУППИРОВАТЬ ПО для всех выбранных полей, кроме агрегатных.
  4. Фильтруем: Используем ИМЕЮЩИЕ для отбора записей, где количество больше единицы.

Посмотрим на пример готового запроса для поиска дублей в документах продажи:


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

Продвинутые техники: КОЛИЧЕСТВО(РАЗЛИЧНЫЕ)

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

Давайте проанализируем ситуацию: если мы ищем подчиненные документы через связь в табличной части, запрос может вернуть столько строк, сколько строк в ТЧ ссылаются на родителя. Чтобы понять, действительно ли создано два разных документа-дубля, мы пишем так:


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

Резюме по решению задачи

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

  1. Для получения подчиненных документов всегда в первую очередь проверяйте наличие Критерия отбора. Это самый производительный метод.
  2. Забудьте про использование В ИЕРАРХИИ для документов — этот оператор для них бесполезен.
  3. При поиске дублей всегда используйте связку СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ.
  4. Помните, что условие на результат агрегатной функции (количество, сумма) никогда не ставится в секции ГДЕ.

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

← На главную