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

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

В процессе поддержки и аудита информационных баз 1С мы часто сталкиваемся с аномалиями данных. Одна из таких ситуаций — наличие документа, который сформировал бухгалтерские проводки (движения по регистру бухгалтерии), но при этом его табличные части (например, "Товары" или "Услуги") абсолютно пусты. Такая ситуация может возникнуть из-за ошибок обмена, некорректного программного вмешательства или ручной корректировки движений.

Рассмотрим подробно, как с помощью языка запросов 1С выявить такие документы. Мы разберем правильную архитектуру запроса, вопросы производительности и объединение условий.

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

Нам необходимо выбрать документы (на примере РеализацияТоваровУслуг), которые удовлетворяют двум условиям одновременно:

  1. Документ имеет записи в регистре бухгалтерии (например, Хозрасчетный).
  2. В документе не заполнены табличные части (строки отсутствуют).

Шаг 1. Выбор источника данных и оптимизация производительности

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

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

Важно: Не используйте виртуальные таблицы (например, РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто), если вам нужно просто проверить наличие записей. Обращение к виртуальной таблице заставляет платформу выполнять сложные соединения с таблицами значений субконто, что значительно замедляет выполнение запроса на больших объемах данных.

Для нашей задачи идеально подходит основная (физическая) таблица регистра:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Хозрасчетный.Регистратор
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный

Использование ключевого слова РАЗЛИЧНЫЕ обязательно, так как один документ может создавать десятки проводок, а нам в выборке документ нужен только один раз.

Шаг 2. Логика поиска "пустоты" (LEFT JOIN ... IS NULL)

Теперь разберем, как определить, что у документа пустая табличная часть. В языке запросов 1С для поиска отсутствующих данных используется классический прием: Левое соединение с последующей проверкой на NULL.

Суть метода:

  1. Мы берем документ (или регистратор из регистра).
  2. Присоединяем к нему таблицу его товаров методом ЛЕВОЕ СОЕДИНЕНИЕ.
  3. Если у документа есть товары, в полях присоединенной таблицы будут данные.
  4. Если товаров нет, в полях будет значение NULL.
  5. В секции ГДЕ мы оставляем только те строки, где есть NULL.

Шаг 3. Итоговый запрос для одной табличной части

Соединим полученные знания. Напишем запрос, который ищет документы, существующие в регистре бухгалтерии, но не имеющие строк в ТЧ "Товары".


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Хозрасчетный.Регистратор КАК СсылкаНаДокумент
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
    	// Присоединяем табличную часть документа
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК РТУ_Товары
        ПО Хозрасчетный.Регистратор = РТУ_Товары.Ссылка
ГДЕ
    // Фильтруем только по нужному типу документа, так как в регистре могут быть разные документы
    Хозрасчетный.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
    // Главное условие: запись в ТЧ не найдена
    И РТУ_Товары.Ссылка ЕСТЬ NULL

Шаг 4. Усложнение задачи: проверка нескольких табличных частей

Документы часто имеют несколько табличных частей. Например, в "Реализации товаров и услуг" есть и Товары, и Услуги. Если мы используем запрос выше, мы можем ошибочно отобрать документ, в котором продали только услугу (ТЧ "Товары" пуста, но документ корректный).

Чтобы найти документы, которые полностью пусты (нет ни товаров, ни услуг), нам нужно сделать левое соединение ко всем значимым таблицам и проверить их все.

Посмотрим на полный код решения:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Хозрасчетный.Регистратор КАК ДокументОшибки
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
        
        // Соединяем с ТЧ Товары
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК ТЧ_Товары
        ПО Хозрасчетный.Регистратор = ТЧ_Товары.Ссылка
        
        // Соединяем с ТЧ Услуги
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Услуги КАК ТЧ_Услуги
        ПО Хозрасчетный.Регистратор = ТЧ_Услуги.Ссылка

ГДЕ
    Хозрасчетный.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
    // Проверяем, что пусто ВЕЗДЕ
    И ТЧ_Товары.Ссылка ЕСТЬ NULL
    И ТЧ_Услуги.Ссылка ЕСТЬ NULL

Обратите внимание на использование логического оператора И в условиях. Документ попадет в выборку только если обе табличные части вернули NULL.

Альтернативный вариант: использование вложенных запросов

Иногда запрос через соединения может быть громоздким для восприятия. Рассмотрим альтернативный подход, который семантически читается как "Выбери документы, которых нет в списке документов с товарами".

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


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Хозрасчетный.Регистратор
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
    Хозрасчетный.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
    И НЕ Хозрасчетный.Регистратор В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                Т.Ссылка
            ИЗ
                Документ.РеализацияТоваровУслуг.Товары КАК Т)
    И НЕ Хозрасчетный.Регистратор В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                У.Ссылка
            ИЗ
                Документ.РеализацияТоваровУслуг.Услуги КАК У)

Примечание по производительности: Современный планировщик SQL-запросов (Query Optimizer) в большинстве случаев приведет оба варианта (JOIN и IN/EXISTS) к схожему плану выполнения. Однако вариант с LEFT JOIN ... IS NULL традиционно считается более предсказуемым и стабильным стандартом в разработке на 1С.

Почему такие документы появляются?

На практике полезно не только найти ошибку, но и понять её причину. Если ваш запрос вернул данные, проверьте следующие гипотезы:

  1. Ручная корректировка. Пользователь установил флаг "Ручная корректировка" в документе, удалил все строки, но вручную вбил проводки в дебет/кредит.
  2. Программный сбой. Обработка загрузки данных создала документ, записала его, сформировала движения программно (набор записей), но упала с ошибкой перед заполнением табличных частей.
  3. Свертка базы. Некорректно выполненная свертка информационной базы могла оставить "хвосты" в виде движений без подтверждающих документов.

Рекомендации

При запуске таких запросов на реальных базах данных обязательно добавляйте отбор по Периоду в таблицу регистра бухгалтерии (Хозрасчетный.Период МЕЖДУ ...). Сканирование всей таблицы регистра за все годы существования базы может вызвать существенную нагрузку на сервер СУБД.

← На главную