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