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