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

Рис.2 Тестовый отчет (С отбором по Назначению НЕ показывает Свободный остаток)

Если проверить в Консоли запросов полный запрос из отчета, сделав отбор по полю Назначение в Подзапрос 1 в секции ГДЕ, то Консоль запросов Свободный остаток показывает.
Интересно, как починить или объяснить...
Рис.3 Консоль запросов с отбором по назначению показывает Свободный остаток

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

ВЫБРАТЬ
ЗапасыИПотребностиОстатки.Номенклатура КАК Номенклатура,
ЗапасыИПотребностиОстатки.Назначение КАК Назначение,
СУММА(ЗапасыИПотребностиОстатки.ВНаличииОстаток) КАК ЗанятыйОстаток
ПОМЕСТИТЬ втЗанятыНаСкладе1
ИЗ
РегистрНакопления.ЗапасыИПотребности.Остатки(
&НаДату {(&НаДату)},
Склад = &Склад1
И Назначение <> ЗНАЧЕНИЕ(Справочник.Назначения.ПустаяСсылка)) КАК ЗапасыИПотребностиОстатки
{ГДЕ
ЗапасыИПотребностиОстатки.Назначение.* КАК НазначениеНаСклад1}
СГРУППИРОВАТЬ ПО
ЗапасыИПотребностиОстатки.Номенклатура,
ЗапасыИПотребностиОстатки.Назначение
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЗапасыИПотребностиОстатки.Номенклатура КАК Номенклатура,
СУММА(ЗапасыИПотребностиОстатки.ВНаличииОстаток) КАК СвободныйОстаток
ПОМЕСТИТЬ втСвободныНаСкладе2
ИЗ
РегистрНакопления.ЗапасыИПотребности.Остатки(
&НаДату {(&НаДату)},
Склад = &Склад2
И Назначение = ЗНАЧЕНИЕ(Справочник.Назначения.ПустаяСсылка)
И Номенклатура В
(ВЫБРАТЬ
Таб.Номенклатура
ИЗ
втЗанятыНаСкладе1 КАК Таб)) КАК ЗапасыИПотребностиОстатки
СГРУППИРОВАТЬ ПО
ЗапасыИПотребностиОстатки.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
втЗанятыНаСкладе1.Номенклатура КАК Номенклатура,
втЗанятыНаСкладе1.Назначение КАК Назначение,
втЗанятыНаСкладе1.ЗанятыйОстаток КАК ЗанятыйОстаток,
ЕСТЬNULL(втСвободныНаСкладе2.СвободныйОстаток, 0) КАК СвободныйОстаток
ИЗ
втЗанятыНаСкладе1 КАК втЗанятыНаСкладе1
ЛЕВОЕ СОЕДИНЕНИЕ втСвободныНаСкладе2 КАК втСвободныНаСкладе2
ПО втЗанятыНаСкладе1.Номенклатура = втСвободныНаСкладе2.Номенклатура
Рис.4 Хотя по факту Вар А и Б сидят на трубе одинаково

Это всё, говорил же - что заметка небольшая =)
Вступайте в нашу телеграмм-группу Инфостарт