В практике разработчика и бухгалтера часто возникает задача контроля полноты выписки регламентированных документов. Одной из самых распространенных является поиск документов РеализацияТоваровУслуг, для которых по какой-то причине не был создан или проведен документ СчетФактураВыданный. Это критично для корректного формирования книги продаж и отчетности по НДС.
В данной статье мы подробно разберем, как правильно составить запрос для решения этой задачи, проанализируем типичные ошибки начинающих разработчиков и рассмотрим нюансы, связанные с современными конфигурациями 1С.
Самый эффективный способ найти отсутствующие связанные данные в языке запросов 1С — это использование конструкции ЛЕВОЕ СОЕДИНЕНИЕ с последующей фильтрацией по пустому значению (NULL) в правой таблице. Рассмотрим логику этого процесса подробнее.
Когда мы соединяем таблицу реализаций с таблицей счетов-фактур, система пытается сопоставить каждую реализацию с соответствующим счетом-фактурой по полю ДокументОснование. Если счет-фактура найден, поля правой таблицы заполняются данными. Если же счета-фактуры в базе нет, все поля из таблицы счетов-фактур для данной реализации будут содержать значение NULL. Именно это значение мы и будем искать в блоке ГДЕ.
Проанализируем правильную структуру запроса:
ВЫБРАТЬ
Реализация.Ссылка КАК РеализацияСсылка,
Реализация.Дата КАК ДатаРеализации,
Реализация.Номер КАК НомерРеализации
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетФактураВыданный КАК СФ
ПО СФ.ДокументОснование = Реализация.Ссылка
ГДЕ
СФ.Ссылка ЕСТЬ NULL
И Реализация.Проведен = ИСТИНА
И Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
Часто начинающие программисты путают порядок таблиц в соединении. Посмотрим на ошибочный пример, который обсуждался на форуме:
// ОШИБОЧНЫЙ ЗАПРОС
ИЗ
Документ.СчетФактураВыданный КАК СчетФактураВыданный
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ПО СчетФактураВыданный.ДокументОснование = РеализацияТоваровУслуг.Ссылка
ГДЕ
СчетФактураВыданный.Ссылка ЕСТЬ NULL
Почему этот запрос не будет работать? В данном случае основной таблицей (левой) выступает СчетФактураВыданный. Запрос выберет все счета-фактуры и попытается найти к ним реализации. Условие СчетФактураВыданный.Ссылка ЕСТЬ NULL никогда не выполнится для существующих записей этой таблицы. Запомните: слева всегда должна стоять та таблица, полноту которой мы проверяем (в нашем случае — Реализации). Для детального изучения механики связывания таблиц можно использовать руководство по соединениям в запросах для начинающих.
В современных типовых решениях (БП 3.0, ERP 2.5, КА 2.5) реализована возможность выписывать один счет-фактуру на несколько документов отгрузки. В этом случае связь между документами хранится не в реквизите шапки ДокументОснование, а в табличной части счета-фактуры, которая обычно называется ДокументыОснования.
Если мы используем старый подход (через реквизит шапки), мы можем получить «ложноположительные» результаты — запрос покажет, что счета-фактуры нет, хотя он существует и просто привязан через табличную часть. Чтобы избежать этого, проанализируем более универсальный запрос:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетФактураВыданный.ДокументыОснования КАК СФОснования
ПО СФОснования.ДокументОснование = Реализация.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &Дата1 И &Дата2
И Реализация.Проведен
И СФОснования.Ссылка ЕСТЬ NULL
Важно: При таком соединении, если у одной реализации будет несколько счетов-фактур (что редко, но возможно), в результате возникнет дублирование строк. Чтобы этого избежать, используйте ключевое слово ВЫБРАТЬ РАЗЛИЧНЫЕ.
Просто найти отсутствие ссылки недостаточно для качественного отчета. Проанализируем ситуацию: в базе может быть много старых черновиков реализаций или документов, помеченных на удаление. Они не требуют счетов-фактур.
При построении запроса обязательно накладывайте следующие фильтры:
Проведен = ИСТИНА — нас интересуют только те документы, которые сделали движения по регистрам.ПометкаУдаления = ЛОЖЬ — исключаем мусорные данные.Если база данных имеет огромный объем, ЛЕВОЕ СОЕДИНЕНИЕ может работать медленнее, чем вложенный запрос с условием исключения. Рассмотрим такой вариант:
ВЫБРАТЬ
Реализация.Ссылка
ИЗ
Документ.RealizationТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &Дата1 И &Дата2
И Реализация.Проведен
И НЕ Реализация.Ссылка В
(ВЫБРАТЬ
СФОснования.ДокументОснование
ИЗ
Документ.СчетФактураВыданный.ДокументыОснования КАК СФОснования)
Этот метод часто оказывается более читаемым, однако стоит помнить, что на уровне SQL-сервера производительность этих двух подходов (JOIN vs NOT IN) может различаться в зависимости от настроек оптимизатора и индексов.
Если задача стоит не перед разработчиком, а перед пользователем, выясним, как найти такие документы без написания кода. В большинстве конфигураций 1С предусмотрены стандартные механизмы:
Таким образом, мы рассмотрели как техническую сторону вопроса (составление запроса с ЛЕВЫМ СОЕДИНЕНИЕМ и фильтром по NULL), так и практические нюансы работы с данными в реальных учетных системах. Для тестирования и отладки таких запросов в рабочей конфигурации подойдёт консоль запросов для 1С на управляемых формах.