Разработка и Конфигурация · 9 мин
Как в 1С выбрать документы с пустой табличной частью
Как в 1С найти документы с пустой табличной частью: запрос с ЛЕВОЕ СОЕДИНЕНИЕ, ГДЕ ЕСТЬ NULL, подзапросом, обходом в коде и в консоли запросов.
Задача найти документы с пустой табличной частью возникает регулярно: при поиске ошибок ввода, подготовке к свёртке базы, проверке обменов или аудите данных. Документ может быть проведён, но не содержать ни одной строки в табличной части «Товары» или «Услуги» — и такие документы нужно отобрать для исправления или удаления.
Штатными средствами интерфейса (отборами списка) эту задачу не решить: отбор по количеству строк табличной части в форме списка недоступен. Поэтому используют язык запросов 1С, обход в коде или внешние инструменты вроде консоли запросов и универсального подбора и обработки объектов.
Ниже разобраны три рабочих способа с готовыми текстами запросов, особенности левого соединения с табличной частью, типичные ошибки и способы проверить, что отбор действительно корректен.
Почему стандартный отбор списка не поможет
В форме списка документа можно отбирать только по реквизитам шапки: дате, номеру, контрагенту, организации и т.п. Табличные части физически хранятся в отдельных таблицах базы данных, и платформа не предоставляет для них отбор в динамическом списке «из коробки».
Даже если добавить в динамический список произвольный запрос с соединением к табличной части, это приведёт к дублированию строк списка (по строке на каждую строку табличной части) и потере стандартных возможностей вроде быстрого поиска. Поэтому правильный путь — отдельный запрос или обработка.
Способ 1. Запрос с левым соединением и условием ЕСТЬ NULL
Классический и самый быстрый способ — левое соединение таблицы документа с его табличной частью. Если у документа нет строк, поля табличной части будут содержать NULL, что и используется как условие отбора.
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Документ,
РеализацияТоваровУслуг.Дата,
РеализацияТоваровУслуг.Номер,
РеализацияТоваровУслуг.Контрагент
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Товары
ПО РеализацияТоваровУслуг.Ссылка = Товары.Ссылка
ГДЕ
Товары.Ссылка ЕСТЬ NULL
И РеализацияТоваровУслуг.Проведен
Обратите внимание на два момента. Во-первых, условие Товары.Ссылка ЕСТЬ NULL проверяет именно ссылку табличной части — она гарантированно заполнена в каждой реальной строке, поэтому NULL однозначно означает отсутствие строк. Во-вторых, условие по табличной части должно стоять в секции ГДЕ, а не в условии соединения ПО, иначе логика левого соединения нарушится.
Дополнительный фильтр РеализацияТоваровУслуг.Проведен отсекает помеченные на удаление и непроведённые документы — обычно интерес представляют именно проведённые. Если нужны все документы, уберите это условие.
Способ 2. Отбор через подзапрос с НЕ В
Альтернатива соединению — подзапрос, выбирающий все документы, у которых есть строки, и исключение их из результата через оператор НЕ В.
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Документ
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
НЕ РеализацияТоваровУслуг.Ссылка В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
Товары.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары)
Этот вариант проще читается, но на больших объёмах данных обычно работает медленнее левого соединения, особенно в файловых базах. На клиент-серверных базах с СУБД MS SQL или PostgreSQL оптимизатор часто преобразует оба варианта в похожий план, но соединение с ЕСТЬ NULL остаётся более предсказуемым.
Сравнение подходов
Быстро и предсказуемо, подходит для больших таблиц. Требует аккуратности с условиями соединения.
Проще для понимания, но медленнее на больших объёмах и чувствителен к NULL в подзапросе.
Не требует знания языка запросов, но медленный: каждая табличная часть вычитывается отдельным обращением.
Способ 3. Программный обход документов в коде
Если запрос по какой-то причине недоступен (например, логика реализуется в обработке проведения или регламентном задании с дополнительными проверками), можно обойти документы выборкой и проверить количество строк у каждого.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Проведен";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
Если ДокументОбъект.Товары.Количество() = 0 Тогда
Сообщить("Пустая табличная часть: " + ДокументОбъект);
КонецЕсли;
КонецЦикла;
Главный недостаток подхода — производительность: каждый вызов ПолучитьОбъект() вычитывает документ целиком, включая все табличные части. На тысячах документов это заметно медленнее одного запроса. Используйте обход только когда нужно не просто найти, а сразу обработать документы объектными методами.
Проверка результата и частые ошибки
После выполнения запроса стоит убедиться, что отбор работает корректно. Откройте два-три найденных документа интерактивно и проверьте, что табличная часть действительно пуста. Затем возьмите документ, которого нет в результате, и убедитесь, что в нём строки есть.
Также полезно проверить обратным запросом: выбрать документы, у которых строки есть, и сравнить суммарное количество с общим числом документов. Сумма «с строками» и «без строк» должна равняться общему количеству документов за период.
Поиск через консоль запросов и готовые обработки
Если писать код не требуется, а нужен разовый анализ, удобнее всего использовать консоль запросов (входит в состав «Инструменты разработчика» и многих типовых конфигураций на БСП). Вставьте текст запроса из первого способа, выполните его и получите список ссылок с возможностью открыть каждый документ.
Для массовой обработки найденных документов подойдёт типовая обработка «Групповое изменение реквизитов» (в конфигурациях на Библиотеке стандартных подсистем) или «Универсальный подбор и обработка объектов»: в ней можно задать произвольный запрос отбора и выполнить над результатом действие — например, пометку на удаление. Действие применяйте только после проверки списка.
- 1Определите, по какой табличной части и по какому виду документов нужен отбор.
- 2Выполните запрос с левым соединением и условием ЕСТЬ NULL в консоли запросов.
- 3Откройте несколько найденных документов и убедитесь, что табличная часть действительно пуста.
- 4Проверьте контрольную сумму: документы со строками + документы без строк = все документы.
- 5Только после проверки выполняйте массовые действия над найденными документами.
Особые случаи и ограничения
Если документ участвует в обменах, пустая табличная часть может быть следствием ошибки выгрузки или конфликта при загрузке. В этом случае корректнее не удалять документ, а исправить его повторной загрузкой из источника. Проверьте журнал регистрации и очереди обмена на наличие ошибок по найденным документам.
В управляемых формах с динамическим списком можно вывести результат запроса как отдельную форму-отчёт, но для разовых задач это избыточно. Также учтите, что виртуальные поля и итоги к табличным частям не применяются — соединение идёт напрямую с физической таблицей табличной части.
Что важно запомнить
Документы с пустой табличной частью отбираются запросом: левое соединение с табличной частью и условие ЕСТЬ NULL по её ссылке. Условие размещается в секции ГДЕ, фильтр по проведённым добавляется отдельно. Перед массовой обработкой результат обязательно проверяется вручную и контрольной суммой.
Частые вопросы
Можно ли найти документы, где табличная часть есть, но все количества равны нулю?
Да, но это другая задача. Нужно соединение с табличной частью и группировка: ВЫБРАТЬ Ссылку, СУММА(Количество) СГРУППИРОВАВ ПО Ссылке ИМЕЮЩИЕ СУММА(Количество) = 0. Условие ЕСТЬ NULL здесь не подходит, так как строки физически существуют.
Работает ли запрос с ЕСТЬ NULL в файловой базе?
Да, конструкция левого соединения с проверкой ЕСТЬ NULL полностью поддерживается платформой независимо от режима работы базы. Разница только в скорости выполнения на больших объёмах.
Как проверить сразу несколько табличных частей одного документа?
Добавьте по одному левому соединению на каждую табличную часть и в секции ГДЕ перечислите условия через И: Товары.Ссылка ЕСТЬ NULL И Услуги.Ссылка ЕСТЬ NULL. Так вы найдёте документы, где пусты обе табличные части. Если достаточно пустоты хотя бы одной, используйте ИЛИ.
Почему запрос возвращает один и тот же документ несколько раз?
Такое бывает, если в соединении ошибочно использовано поле, не являющееся уникальным, или если соединение выполнено с другой таблицей без корректного условия. При соединении документа с собственной табличной частью по Ссылке и условии ЕСТЬ NULL дублей быть не должно — у документа без строк будет ровно одна строка результата.
Можно ли увидеть пустые табличные части без программирования вообще?
Частично: в типовых конфигурациях есть отчёты и обработки контроля данных, но универсального штатного отчёта «документы без строк» нет. Проще всего попросить специалиста выполнить готовый запрос в консоли запросов — это занимает несколько минут и не требует изменения конфигурации.