В практике разработки на платформе 1С регулярно возникает задача: отобрать документы определенного вида, по которым еще не созданы подчиненные или связанные документы цепочки (например, найти реализации, по которым не оформлена отгрузка, или счета без оплат). Разберем по шагам, как правильно составить такой запрос, учесть статус документов, обработать частичные отгрузки и избежать типичных ошибок с задвоением данных.
Если подчиненный документ (в нашем примере — Отгрузка) содержит реквизит-ссылку на документ основания (Реализация), мы не можем отфильтровать реализации простым условием в самом документе. Чтобы исключить проведенные цепочки, используем ЛЕВОЕ СОЕДИНЕНИЕ таблицы реализаций с таблицей отгрузок.
При левом соединении для каждой реализации ищется соответствующая отгрузка. Если отгрузки нет, поля присоединенной таблицы заполняются значением NULL. Наложив условие ГДЕ Отгрузка.Ссылка ЕСТЬ NULL, мы оставляем только те реализации, для которых связанная отгрузка отсутствует.
Рассмотрим базовый пример запроса:
ВЫБРАТЬ
ДокРеализация.Ссылка КАК Реализация
ИЗ
Документ.Реализация КАК ДокРеализация
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Отгрузка КАК ДокОтгрузка
ПО ДокРеализация.Ссылка = ДокОтгрузка.Реализация
И ДокОтгрузка.Проведен = ИСТИНА
ГДЕ
ДокРеализация.Проведен = ИСТИНА
И ДокОтгрузка.Ссылка ЕСТЬ NULL
Проанализируем ключевые моменты, которые необходимо учитывать при построении таких запросов:
ДокОтгрузка.Проведен = ИСТИНА, непроведенный черновик отгрузки ошибочно исключит реализацию из выборки. При этом условие проведения подчиненного документа следует указывать именно в секции ПО соединения, а не в секции ГДЕ, чтобы не превратить левое соединение во внутреннее.
ВЫБРАТЬ
ДокРеализация.Ссылка КАК Реализация
ИЗ
Документ.Реализация КАК ДокРеализация
ГДЕ
ДокРеализация.Проведен = ИСТИНА
И ДокРеализация.Ссылка НЕ В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ДокОтгрузка.Реализация
ИЗ
Документ.Отгрузка КАК ДокОтгрузка
ГДЕ
ДокОтгрузка.Проведен = ИСТИНА)
Ситуация усложняется, если по одной реализации может быть несколько документов отгрузки, либо товар отгружается по частям. В этом случае простого факта наличия документа Отгрузка недостаточно — нужно сравнивать количество товара в реализации и фактически отгруженное количество.
Внимание: Прямое соединение табличных частей документов Реализация.Товары и Отгрузка.Товары приводит к декартову произведению строк при наличии нескольких документов отгрузки, из-за чего количество товаров многократно задваивается.
Разберем по шагам правильный алгоритм решения задачи с использованием временных таблиц:
Посмотрим на полный текст комплексного запроса:
ВЫБРАТЬ
ТЧ_Реализация.Ссылка КАК Реализация,
ТЧ_Реализация.Номенклатура КАК Номенклатура,
СУММА(ТЧ_Реализация.Количество) КАК КоличествоПоПлану
ПОМЕСТИТЬ ВТ_ТоварыРеализации
ИЗ
Документ.Реализация.Товары КАК ТЧ_Реализация
ГДЕ
ТЧ_Реализация.Ссылка.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
ТЧ_Реализация.Ссылка,
ТЧ_Реализация.Номенклатура
ИНДЕКСИРОВАТЬ ПО
Реализация,
Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ДокОтгрузка.Реализация КАК Реализация,
ТЧ_Отгрузка.Номенклатура КАК Номенклатура,
СУММА(ТЧ_Отгрузка.Количество) КАК КоличествоОтгружено
ПОМЕСТИТЬ ВТ_ТоварыОтгрузки
ИЗ
Документ.Отгрузка.Товары КАК ТЧ_Отгрузка
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Отгрузка КАК ДокОтгрузка
ПО ТЧ_Отгрузка.Ссылка = ДокОтгрузка.Ссылка
ГДЕ
ДокОтгрузка.Проведен = ИСТИНА
И ДокОтгрузка.Реализация В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ВТ_ТоварыРеализации.Реализация
ИЗ
ВТ_ТоварыРеализации)
СГРУППИРОВАТЬ ПО
ДокОтгрузка.Реализация,
ТЧ_Отгрузка.Номенклатура
ИНДЕКСИРОВАТЬ ПО
Реализация,
Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Реализации.Реализация КАК Реализация,
Реализации.Номенклатура КАК Номенклатура,
Реализации.КоличествоПоПлану КАК Заказано,
ЕСТЬNULL(Отгрузки.КоличествоОтгружено, 0) КАК Отгружено,
Реализации.КоличествоПоПлану - ЕСТЬNULL(Отгрузки.КоличествоОтгружено, 0) КАК ОстатокКОтгрузке
ИЗ
ВТ_ТоварыРеализации КАК Реализации
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ТоварыОтгрузки КАК Отгрузки
ПО Реализации.Реализация = Отгрузки.Реализация
И Реализации.Номенклатура = Отгрузки.Номенклатура
ГДЕ
Реализации.КоличествоПоПлану - ЕСТЬNULL(Отгрузки.КоличествоОтгружено, 0) > 0
Построение тяжелых аналитических отчетов и выборок напрямую по табличным частям документов создает высокую нагрузку на СУБД, сканирует физические таблицы целиком и может вызывать длительные блокировки данных. Для постоянного контроля неотгруженных или неоплаченных позиций в архитектуре 1С рекомендуется использовать Регистры накопления с видом «Остатки» (например, регистр заказов или взаиморасчетов). В таком случае расчет остатков к отгрузке сводится к обращению к быстрой виртуальной таблице Остатки без необходимости связывать цепочки документов вручную.