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

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

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

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

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


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


Какой вариант в данной ситуации будет более рациональным? Кто что думает по этому поводу?
Найденные решения
5. Boneman 294 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 294 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 3 04.12.22 17:46 Сейчас в теме
Вот подобный пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КодыНоменклатуры.Код77 КАК Код77,
| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
| ТоварыНаСкладахОстатки.ВНаличииОстаток КАК ВНаличииОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, Склад В (&СписокЗначенийСклады)) КАК ТоварыНаСкладахОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| НоменклатураДополнительныеРеквизиты.Ссылка КАК Номенклатура,
| НоменклатураДополнительныеРеквизиты.Значение КАК Код77
| ИЗ
| Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
| ГДЕ
| НоменклатураДополнительныеРеквизиты.Свойство = &Свойство) КАК КодыНоменклатуры
| ПО ТоварыНаСкладахОстатки.Номенклатура = КодыНоменклатуры.Номенклатура
|ГДЕ
| ТоварыНаСкладахОстатки.Номенклатура.ВидНоменклатуры В(&ВидНоменклатуры)
|
|УПОРЯДОЧИТЬ ПО
| ТоварыНаСкладахОстатки.Номенклатура.Наименование";
Список = Новый Массив;
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Продукция"));
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Полуфабрикаты"));
Если Объект.ПоказатьОстаткиМатериалов Тогда
Список.Добавить(Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Материалы производства"));
КонецЕсли;
Запрос.УстановитьПараметр("ВидНоменклатуры",Список);
Запрос.УстановитьПараметр("ДатаОтчета",НачалоДня(НачДата));
СписокЗначенийСклады = Новый СписокЗначений;
Если НЕ ЗначениеЗаполнено(Объект.Склад) Тогда
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад1"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад2"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад3"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад4"));
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад5"));
Иначе
СписокЗначенийСклады.Добавить(Объект.Склад));
Если Объект.Склад = Справочники.Склады.НайтиПоНаименованию("Склад1") Тогда
СписокЗначенийСклады.Добавить(Справочники.Склады.НайтиПоНаименованию("Склад3"));
КонецЕсли;
КонецЕсли;
Запрос.УстановитьПараметр("Склад",СписокЗначенийСклады);
Запрос.УстановитьПараметр("Свойство",ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя","Код77"));

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

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

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

Инженер 1С
Ессентуки
зарплата от 120 000 руб. до 144 000 руб.
Полный день

Программист 1С
Санкт-Петербург
зарплата от 100 000 руб. до 250 000 руб.
Полный день

Программист 1С
Краснознаменск (Московская обл.)
зарплата от 150 000 руб. до 250 000 руб.
Полный день

Специалист техподдержки
Краснознаменск (Московская обл.)
зарплата от 50 000 руб. до 100 000 руб.
Полный день