Остатки по 2 складам

1. MontikM 30.01.17 06:38 Сейчас в теме
Здравствуйте.

Возник следующий вопрос. Нужно получить остатки товара по 2 складам (остатки по каждому из этих складов должны идти отдельной колонкой). При этом нужно проигнорировать те позиции товара, которые есть на 2 складе, но нет на 1 складе.

Придумал 2 пути решения

1) Отдельно рассчитывать остатки для одного склада и для другого, а потом объединять их. Недостаток данного варианта является, то что приходится обращаться к регистру остатков дважды. Запрос будет выглядеть примерно так:
ВЫБРАТЬ
	СвободныеОстаткиОстатки.ВНаличииОстаток,
	СвободныеОстаткиОстатки.Номенклатура,
	СвободныеОстаткиОстатки1.ВНаличииОстаток КАК ВНаличииОстаток1
ИЗ
	РегистрНакопления.СвободныеОстатки.Остатки(&Дата, Склад = &Склад1) КАК СвободныеОстаткиОстатки
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СвободныеОстатки.Остатки(&Дата, Склад = &Склад2) КАК СвободныеОстаткиОстатки1
		ПО СвободныеОстаткиОстатки.Номенклатура = СвободныеОстаткиОстатки1.Номенклатура
ГДЕ
	СвободныеОстаткиОстатки.ВНаличииОстаток > 0
Показать


2) Оба склада поместить в список значений. Далее выбрать запросом данные сразу по двум складам. После чего результат выгрузить в таблицу значений и обработать её.
Обращение к регистру остатков одно, но зато дополнительно будет обрабатываться таблица значений.
Запрос будет выглядеть примерно так:
ВЫБРАТЬ
	СвободныеОстаткиОстатки.ВНаличииОстаток,
	СвободныеОстаткиОстатки.Склад,
	СвободныеОстаткиОстатки.Номенклатура
ИЗ
	РегистрНакопления.СвободныеОстатки.Остатки(&Дата, Склад В (&СписокЗначенийСклады)) КАК СвободныеОстаткиОстатки


Какой вариант в данной ситуации будет более рациональным? Кто что думает по этому поводу?
По теме из базы знаний
Найденные решения
5. Boneman 298 30.01.17 10:07 Сейчас в теме
мне одному кажется, что тут вообще никаких соединений не нужно в запросе ?
Выбираем остатки, используем В (&Склады) или &Склад1 Или &Склад2
где остатки, там вычисляемое поле
Выбор
Когда Выборка.Склад = &Склад1 тогда остаток Выборка.Остаток 
Иначе 0
Конец

По второму складу отдельное вычисляемое поле.
Группируем по номенклатуре, склад нам уже не нужен.
И ставим на выходе условие, "ГДЕ Колонка1>0 и Колонка2>0"

P.S.
Готовый запрос рисовать лень, но в целом идея понятна.
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. PhoenixAOD 62 30.01.17 07:14 Сейчас в теме
(1) зачем что то придумывать? уже все давно придумано за Вас, почитайте разницу между левым, правым и правым соединением, примеров по соединениям в интернете очень много.
3. MontikM 30.01.17 09:42 Сейчас в теме
(2) Не понял Вашу мысль... Вы думаете, что можно левое/правое соединение использовать как-то более рационально, чем это предложил сделать я в своём первом варианте?
Информации по соединениям в интернете много, но нигде не рассматривается (по крайней мере я не нашёл) вопрос как лучше строить соединение, когда одна и та же таблица соединятеся "сама с собой"
8. PhoenixAOD 62 30.01.17 10:23 Сейчас в теме
(3) я отбирал обычно в разные временные таблицы и с этим уже работал.
10. MontikM 30.01.17 10:30 Сейчас в теме
(8) Ну да, про временные таблицы я тоже думал.

Запрос примерно такой получался:
ВЫБРАТЬ
	СвободныеОстаткиОстатки.ВНаличииОстаток,
	СвободныеОстаткиОстатки.Склад,
	СвободныеОстаткиОстатки.Номенклатура
ПОМЕСТИТЬ ТаблицаОстатков
ИЗ
	РегистрНакопления.СвободныеОстатки.Остатки(&Дата, (Склад = &Склад1 Или Склад = &Склад2)) КАК СвободныеОстаткиОстатки
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ТаблицаОстатков.ВНаличииОстаток,
	ТаблицаОстатков.Номенклатура,
	ТаблицаОстатков1.ВНаличииОстаток КАК ВНаличииОстаток1
ИЗ
	ТаблицаОстатков КАК ТаблицаОстатков
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаОстатков КАК ТаблицаОстатков1
		ПО ТаблицаОстатков.Номенклатура = ТаблицаОстатков1.Номенклатура
ГДЕ
	ТаблицаОстатков.Склад = &Склад1
	И ТаблицаОстатков.ВНаличииОстаток > 0
	И ТаблицаОстатков1.Склад = &Склад2
Показать


Но конкретно в моём случае, наиболее оптимальный вариант озвучен в (5), поскольку в моём конкретном случае ещё один склад в этой обработке вряд ли появится.

Ну а так, со временными таблицами вариант более универсальный.
4. vipetrov2 30.01.17 09:49 Сейчас в теме
Пользуйся 1 вариантом, только соединение делай внутреннее и без ГДЕ.

ВЫБРАТЬ
    СвободныеОстаткиОстатки.ВНаличииОстаток,
    СвободныеОстаткиОстатки.Номенклатура,
    СвободныеОстаткиОстатки1.ВНаличииОстаток КАК ВНаличииОстаток1
ИЗ
    РегистрНакопления.СвободныеОстатки.Остатки(&Дата, Склад = &Склад1) КАК СвободныеОстаткиОстатки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.СвободныеОстатки.Остатки(&Дата, Склад = &Склад2) КАК СвободныеОстаткиОстатки1
        ПО СвободныеОстаткиОстатки.Номенклатура = СвободныеОстаткиОстатки1.Номенклатура
Показать
6. MontikM 30.01.17 10:10 Сейчас в теме
(4) (4) Внутренее соединение здесь сработает не совсем верно. Поскольку оно отсечёт ту номенклатуру, которая есть на складе 1, но нет на складе 2. А нужно отсечь только ту, которой нет на складе 1, при этом она может присутствовать на складе 2.

Меня в этом первом варианте смущает то что запрос будет обходить регистр остатков дважды. Что на мой взгляд может быть не оптимально...
5. Boneman 298 30.01.17 10:07 Сейчас в теме
мне одному кажется, что тут вообще никаких соединений не нужно в запросе ?
Выбираем остатки, используем В (&Склады) или &Склад1 Или &Склад2
где остатки, там вычисляемое поле
Выбор
Когда Выборка.Склад = &Склад1 тогда остаток Выборка.Остаток 
Иначе 0
Конец

По второму складу отдельное вычисляемое поле.
Группируем по номенклатуре, склад нам уже не нужен.
И ставим на выходе условие, "ГДЕ Колонка1>0 и Колонка2>0"

P.S.
Готовый запрос рисовать лень, но в целом идея понятна.
7. MontikM 30.01.17 10:10 Сейчас в теме
(5) Благодарю!
Это, наверное, самое оптимальное решение.
9. PhoenixAOD 62 30.01.17 10:24 Сейчас в теме
(5) да удобно, а если заведут еще один склад? опять вычисляемое поле лезть?
12. spacecraft 30.01.17 10:59 Сейчас в теме
(5) только это не согласуется с:
При этом нужно проигнорировать те позиции товара, которые есть на 2 складе, но нет на 1 складе.
11. MontikM 30.01.17 10:37 Сейчас в теме
Благодарю всех за участие в обсуждении!
13. user1032515 4 04.12.22 17:46 Сейчас в теме
Вот подобный пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КодыНоменклатуры.Код77 КАК Код77,
| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
| ТоварыНаСкладахОстатки.ВНаличииОстаток КАК ВНаличииОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, Склад В (&СписокЗначенийСклады)) КАК ТоварыНаСкладахОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| НоменклатураДополнительныеРеквизиты.Ссылка КАК Номенклатура,
| НоменклатураДополнительныеРеквизиты.Значение КАК Код77
| ИЗ
| Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
| ГДЕ
| НоменклатураДополнительныеРеквизиты.Свойство = &Свойство) КАК КодыНоменклатуры
| ПО ТоварыНаСкладахОстатки.Номенклатура = КодыНоменклатуры.Номенклатура
|ГДЕ
| ТоварыНаСкладахОстатки.Номенклатура.ВидНоменклатуры В(&ВидНоменклатуры)
|
|УПОРЯДОЧИТЬ ПО
| ТоварыНаСкладахОстатки.Номенклатура.Наименование";
Список = Новый Массив;
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Продукция"));
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Полуфабрикаты"));
Если Объект.ПоказатьОстаткиМатериалов Тогда
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Материалы производства"));
КонецЕсли;
Запрос.УстановитьПараметр("ВидНоменклатуры",Список);
Запрос.УстановитьПараметр("ДатаОтчета",НачалоДня(НачДата));
СписокЗначенийСклады = Новый СписокЗначений;
Если НЕ ЗначениеЗаполнено(Объект.Склад) Тогда
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад1"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад2"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад3"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад4"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад5"));
Иначе
СписокЗначенийСклады.Добавить(Объект.Склад));
Если Объект.Склад = Справочники.Склады.НайтиПоНаименованию("Склад1") Тогда
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад3"));
КонецЕсли;
КонецЕсли;
Запрос.УстановитьПараметр("Склад",СписокЗначенийСклады);
Запрос.УстановитьПараметр("Свойство",ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя","Код77"));

РезультатЗапроса = Запрос.Выполнить();

В Инструментарии разработчика работает на "ура", а в модуле ошибка:

Не задано значение параметра "СписокЗначенийСклады"
РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, Склад В(<<?>>&СписокЗначенийСклады)) КАК ТоварыНаСкладахОстатки
Прикрепленные файлы:
14. user1032515 4 04.12.22 17:48 Сейчас в теме
Делал и не СписокЗначений, а Массив, ошибка такая же
15. user1032515 4 04.12.22 19:30 Сейчас в теме
Прошу прощения, сам и нашел ошибку - Параметр неправильно установил, потому что менял условие
Запрос.УстановитьПараметр("СписокЗначенийСклады",СписокЗначенийСклады);
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот