gifts2017

Запрос стоимости партии на даты документов одним запросом (УТ 10)

Опубликовал koder (bashhhh) в раздел Программирование - Практика программирования

Ниже приведен запрос, который получает стоимость партии на дату документа.
Такой запрос нужен, когда документ не делает движений по регистру Партии товаров.
В УТ10 это документ Перемещение товаров, Приходный и Расходный ордера при отключенной настройке "Вести учет партий в разрезе складов"

Запрос составлен на примере документа Приходный ордер на товары.

В запросе есть виртуальная таблица, в которой получаем данные документов и потом к нему присоединяем слева Партии.ОстаткиИОбороты, чтобы получить период последнего измениения. Этот период должен быть максимальным, но меньше или равен дате документа.

Остались сомнения по получению остатка партии.

В данном случае Цена себестоимости = (НачСтоимость + ПриходСтоимость + КонСтоимость) / (НачКоличестов + ПриходКоличество + КонКоличество).

Возможно есть более оптимальные способы получения стоимости партии.

Любая критика приветствуется.


Текст запроса:

ВЫБРАТЬ
    ПриходныйОрдерНаТоварыТовары.Ссылка.Дата КАК ПериодДень,
    ПриходныйОрдерНаТоварыТовары.Ссылка КАК Документ,
    ПриходныйОрдерНаТоварыТовары.Номенклатура КАК Номенклатура,
    СУММА(ПриходныйОрдерНаТоварыТовары.Количество) КАК Количество
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.ПриходныйОрдерНаТовары.Товары КАК ПриходныйОрдерНаТоварыТовары
ГДЕ
    ПриходныйОрдерНаТоварыТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
    И ПриходныйОрдерНаТоварыТовары.Ссылка.Проведен

СГРУППИРОВАТЬ ПО
    ПриходныйОрдерНаТоварыТовары.Ссылка,
    ПриходныйОрдерНаТоварыТовары.Номенклатура,
    ПриходныйОрдерНаТоварыТовары.Ссылка.Дата
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВложенныйЗапрос.Документ,
    ВложенныйЗапрос.Номенклатура,
    ВЫБОР
        КОГДА ВложенныйЗапрос.Колчество <> 0
            ТОГДА ВложенныйЗапрос.Себестоимость / ВложенныйЗапрос.Колчество
        ИНАЧЕ 0
    КОНЕЦ КАК ЦенаСебестоимости
ПОМЕСТИТЬ ВТ_Себестоимость
ИЗ
    (ВЫБРАТЬ
        ВложенныйЗапрос.Документ КАК Документ,
        ВложенныйЗапрос.Номенклатура КАК Номенклатура,
        СУММА(Партии.КоличествоНачальныйОстаток + Партии.КоличествоПриход + Партии.КоличествоКонечныйОстаток) КАК Колчество,
        СУММА(Партии.СтоимостьНачальныйОстаток + Партии.СтоимостьПриход + Партии.СтоимостьКонечныйОстаток) КАК Себестоимость
    ИЗ
        (ВЫБРАТЬ
            ВТ_Документы.Документ КАК Документ,
            ВТ_Документы.Номенклатура КАК Номенклатура,
            МАКСИМУМ(ПартииТоваровНаСкладахОстаткиИОбороты.Период) КАК ДатаОстатков
        ИЗ
            ВТ_Документы КАК ВТ_Документы
                ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(
                        &НачалоПериода,
                        &КонецПериода,
                        Регистратор,
                        ,
                        Номенклатура В
                            (ВЫБРАТЬ
                                ВТ_Документы.Номенклатура
                            ИЗ
                                ВТ_Документы КАК ВТ_Документы)) КАК ПартииТоваровНаСкладахОстаткиИОбороты
                ПО ВТ_Документы.ПериодДень >= ПартииТоваровНаСкладахОстаткиИОбороты.Период
                    И ВТ_Документы.Номенклатура = ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура
        
        СГРУППИРОВАТЬ ПО
            ВТ_Документы.Документ,
            ВТ_Документы.Номенклатура) КАК ВложенныйЗапрос
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(
                    &НачалоПериода,
                    &КонецПериода,
                    Регистратор,
                    ,
                    Номенклатура В
                        (ВЫБРАТЬ
                            ВТ_Документы.Номенклатура
                        ИЗ
                            ВТ_Документы КАК ВТ_Документы)) КАК Партии
            ПО ВложенныйЗапрос.ДатаОстатков = Партии.Период
                И ВложенныйЗапрос.Номенклатура = Партии.Номенклатура
    
    СГРУППИРОВАТЬ ПО
        ВложенныйЗапрос.Документ,
        ВложенныйЗапрос.Номенклатура) КАК ВложенныйЗапрос
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Документы.ПериодДень,
    ВТ_Документы.Документ,
    ВТ_Документы.Номенклатура,
    ВТ_Документы.Количество,
    ВТ_Документы.Количество * ЕСТЬNULL(ВТ_Себестоимость.ЦенаСебестоимости, 0) КАК Себестоимость
ИЗ
    ВТ_Документы КАК ВТ_Документы
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Себестоимость КАК ВТ_Себестоимость
        ПО ВТ_Документы.Документ = ВТ_Себестоимость.Документ
            И ВТ_Документы.Номенклатура = ВТ_Себестоимость.Номенклатура

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Андрей Карпов (karpik666) 31.03.15 19:23
Я видимо чего-то не понимаю, но зачем получать партии в документах, где партионный учет отключен? И почему нельзя использовать регистр ПродажиСебестоимость для получения себестоимости? В общем куча критики и по поводу самого запроса, представляю сколкько времени он будет формироваться. Посмотрите стандарты разработки фирмы 1С, очень доходчиво объясняется как следует использовать вложенные запросы и временные таблицы.
2. Роман С (Dach) 31.03.15 21:38
Я, конечно, извиняюсь, но соединение с виртуальной таблицей "остатки и обороты", да еще и во вложенном запросе...
Почитайте литературу по написанию запросов, собственно и на ИС много статей, например http://infostart.ru/public/165456/ или http://infostart.ru/public/158617/

Да, и публикации - это не форум, здесь делятся интересными разработками, а Ваша на таковую ну никак не тянет....
3. Caponid V (caponid) 01.04.15 09:12
я так тоже баловался... вот мой вариант с фифо или лифо с получением полной таблицы списания
только с использованием ВТ и списанием пустой партии с количеством если нехватает
ВЫБРАТЬ
	РасходныйОрдер.Ссылка КАК Регистратор,
	РасходныйОрдер.Дата КАК Период,
	РасходныйОрдер.Организация,
	РасходныйОрдер.Склад,
	РасходныйОрдер.МоментВремени
ПОМЕСТИТЬ втШапка
ИЗ
	Документ.РасходныйОрдер КАК РасходныйОрдер
ГДЕ
	РасходныйОрдер.Ссылка = &Ссылка
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	втШапка.Организация,
	втШапка.Склад,
	ТЧТовары.Номенклатура,
	ТЧТовары.Качество,
	ТЧТовары.Количество КАК КоличествоДокумента
ПОМЕСТИТЬ втТЧ
ИЗ
	Документ.РасходныйОрдер.Товары КАК ТЧТовары
		ЛЕВОЕ СОЕДИНЕНИЕ втШапка КАК втШапка
		ПО (ИСТИНА)
ГДЕ
	ТЧТовары.Ссылка = &Ссылка
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	СебестоимостьТоваровОстатки.Организация КАК Организация,
	СебестоимостьТоваровОстатки.Склад КАК Склад,
	СебестоимостьТоваровОстатки.Номенклатура КАК Номенклатура,
	СебестоимостьТоваровОстатки.Качество КАК Качество,
	СебестоимостьТоваровОстатки.ДокументПартии КАК Партия,
	СебестоимостьТоваровОстатки.ДокументПартии.МоментВремени КАК МоментВремени,
	СебестоимостьТоваровОстатки.КоличествоОстаток КАК КоличествоПартии,
	СебестоимостьТоваровОстатки.СуммаОстаток КАК СуммаПартии,
	ВЫРАЗИТЬ(ВЫБОР
			КОГДА СебестоимостьТоваровОстатки.КоличествоОстаток = 0
				ТОГДА 0
			ИНАЧЕ СебестоимостьТоваровОстатки.СуммаОстаток / СебестоимостьТоваровОстатки.КоличествоОстаток
		КОНЕЦ КАК ЧИСЛО(15, 3)) КАК ЦенаПартии
ПОМЕСТИТЬ втОстатки
ИЗ
	РегистрНакопления.СебестоимостьТоваров.Остатки(
			,
			(Организация, Склад, Номенклатура, Качество) В
				(ВЫБРАТЬ
					втТЧ.Организация,
					втТЧ.Склад,
					втТЧ.Номенклатура,
					втТЧ.Качество
				ИЗ
					втТЧ КАК втТЧ)) КАК СебестоимостьТоваровОстатки
ГДЕ
	СебестоимостьТоваровОстатки.КоличествоОстаток > 0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	втТЧ.Организация,
	втТЧ.Склад,
	втТЧ.Номенклатура,
	втТЧ.Качество,
	NULL,
	ВЫБОР
		КОГДА &ФИФО
			ТОГДА ДАТАВРЕМЯ(3999, 11, 1)
		ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
	КОНЕЦ,
	ВЫРАЗИТЬ(9999999999 КАК ЧИСЛО(15, 3)),
	0,
	0
ИЗ
	втТЧ КАК втТЧ

ИНДЕКСИРОВАТЬ ПО
	Номенклатура
    	
;

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

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	втДанные.Организация,
	втДанные.Склад,
	втДанные.Номенклатура,
	втДанные.Качество,
	втДанные.Партия,
	МАКСИМУМ(втДанные.КоличествоДокумента) КАК КоличествоДокумента,
	МАКСИМУМ(втДанные.КоличествоПартии) КАК КоличествоПартии,
	МАКСИМУМ(втДанные.СуммаПартии) КАК СуммаПартии,
	МАКСИМУМ(втДанные.ЦенаПартии) КАК ЦенаПартии,
	СУММА(втДанные.НакопительныйИтогКоличество) КАК НакопительныйИтогКоличество
ПОМЕСТИТЬ втДанные2
ИЗ
	втДанные КАК втДанные

СГРУППИРОВАТЬ ПО
	втДанные.Организация,
	втДанные.Склад,
	втДанные.Номенклатура,
	втДанные.Качество,
	втДанные.Партия
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	втДанные2.Организация,
	втДанные2.Склад,
	втДанные2.Номенклатура,
	втДанные2.Качество,
	втДанные2.Партия,
	втДанные2.КоличествоДокумента,
	втДанные2.КоличествоПартии,
	втДанные2.СуммаПартии,
	втДанные2.ЦенаПартии,
	втДанные2.НакопительныйИтогКоличество,
	втДанные2.КоличествоДокумента - втДанные2.НакопительныйИтогКоличество КАК ОсталосьСписатьКоличество
ПОМЕСТИТЬ втДанные3
ИЗ
	втДанные2 КАК втДанные2
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	втШапка.Период,
	втШапка.Регистратор,
	втДанные3.Организация,
	втДанные3.Склад,
	втДанные3.Номенклатура,
	втДанные3.Качество,
	втДанные3.Партия,
	ВЫБОР
		КОГДА втДанные3.ОсталосьСписатьКоличество = втДанные3.КоличествоПартии
			ТОГДА втДанные3.ОсталосьСписатьКоличество
		ИНАЧЕ втДанные3.КоличествоПартии
	КОНЕЦ КАК Количество,
	ВЫБОР
		КОГДА втДанные3.ОсталосьСписатьКоличество = втДанные3.КоличествоПартии
			ТОГДА ВЫБОР
					КОГДА втДанные3.СуммаПартии - втДанные3.ОсталосьСписатьКоличество * втДанные3.ЦенаПартии = 0
						ТОГДА втДанные3.СуммаПартии
					ИНАЧЕ втДанные3.ОсталосьСписатьКоличество * втДанные3.ЦенаПартии
				КОНЕЦ
		ИНАЧЕ втДанные3.СуммаПартии
	КОНЕЦ КАК Сумма,
	ВЫБОР
		КОГДА втДанные3.Партия ЕСТЬ NULL 
			ТОГДА ИСТИНА
		ИНАЧЕ ЛОЖЬ
	КОНЕЦ КАК Недостача
ИЗ
	втДанные3 КАК втДанные3
		ЛЕВОЕ СОЕДИНЕНИЕ втШапка КАК втШапка
		ПО (ИСТИНА)
ГДЕ
	втДанные3.НакопительныйИтогКоличество = втДанные3.КоличествоДокумента

...Показать Скрыть
4. koder (bashhhh) 01.04.15 11:20
(1) karpik666, Снабженцы поставили задачу получить отчет. где видно себестоимость перевезенного груза за период. Другого способа получить себестоимость на дату документа не нашел, если подскажите - буду рад.
5. koder (bashhhh) 01.04.15 11:36
(1) karpik666, Стандарты обязательно посмотрю. По скорости запрос за 2014г в базе, где 2200 приходных ордеров, номенклатуры около 5000 элементов выполнился за 10 сек. это долго?
6. koder (bashhhh) 01.04.15 11:39
(2) Dach, Спасибо за статьи, обязательно прочитаю. Я только ЗА оптимизацию кода.
А запрос выложил в публикации, потому что не нашел в интернете подобного, возможно, кому-нибудь пригодится.
И конечно же, почитать комментарии и мнения знающих специалистов.
7. Caponid V (caponid) 02.04.15 09:29
(5) bashhhh, для такого небольшого количества - это долго.
явно неоптимальный план запроса - надо перевести вложенные запросы на временные таблицы.
потом можно еще посмотреть по размерам ВТ в сторону индексации - если записей ВТ много и индекс по соединяемому полу получается селективный - тогда можно и проиндексировать ВТ - затраты на построение индекса окупятся при соединении или выборке.

5-100 записей в таблице индексировать не стоит - все равно будет использоваться скан таблицы а не поиск по индексу
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа