Срез последних на каждую дату в СКД

С задачей получения среза последних на каждую дату рано или поздно сталкиваются все. Безусловно, это задача достаточно просто решается запросом с соединением по максимальной дате из меньших или равных дат. Но эту же задачу можно решить и с помощью компоновки данных. Не будем рассуждать о том, какой из способов более производителен, все может зависеть от конкретной задачи.
Первый набор данных:

В качестве примера, создадим отчет по продажам, в котором отдельной колонкой будем выводить цену из прайса на дату продажи.

Создадим набор данных-запрос “ПродажиОбороты”:

"ВЫБРАТЬ    
	ПродажиОбороты.Период КАК Дата,
	ПродажиОбороты.Контрагент КАК Контрагент,
	ПродажиОбороты.Номенклатура КАК Номенклатура,
	ПродажиОбороты.КоличествоОборот КАК Количество,
	ПродажиОбороты.СтоимостьОборот КАК Стоимость
	{ВЫБРАТЬ    
		Дата,    
		Контрагент.*,    
		Номенклатура.*,    
		Количество,    
		Стоимость}
ИЗ    
	РегистрНакопления.Продажи.Обороты({(&НачалоПериода)},{(&КонецПериода)}, День, ) КАК ПродажиОбороты
 
{ГДЕ    
	ПродажиОбороты.Период,    
	ПродажиОбороты.Контрагент.*,    
	ПродажиОбороты.Номенклатура.*,    
	ПродажиОбороты.КоличествоОборот,    
	ПродажиОбороты.СтоимостьОборот}"

Рис. 1 Вкладка ресурсы набора данных ПродажиОбороты

Рис. 2 Настройки отчета

 

Сейчас наш отчет будет иметь следующий вид:

 

Рис. 3 Формирование отчета с одним набором данных

Теперь необходимо добавить в отчет колонку “Цена по прайсу”, которая будет подтягиваться из регистра сведений “Цены номенклатуры” на дату продажи.

Второй набор данных:

Добавим второй набор данных-запрос “Цены”, цены будем брать для фиксированного типа цен:

"ВЫБРАТЬ    
	&Дата КАК Дата,    
	ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,    
	ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
	{ВЫБРАТЬ    
		Дата,    
		Номенклатура.*,    
		Цена}
ИЗ    
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, Номенклатура = &Номенклатура и ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних	
{ГДЕ    
	(&Дата), 
	ЦеныНоменклатурыСрезПоследних.Номенклатура.*,    
	ЦеныНоменклатурыСрезПоследних.Цена}"

В данном наборе данных три параметра: Дата, Номенклатура и тип цен. Из низ самые интересные Дата и Номенклатура. Они будут использованы при соединении наборов данных, причем параметр данных присутствует как в параметрах виртуальной таблицы, так и в выбранных полях.

Соединения наборов:

Приступим к основной “фишке” данного метода – соединениям наборов:

Рис. 4 Соединение наборов данных

Здесь самое основное правильно настроить параметры. Если указан параметр,то  СКД передает в приемник связи параметры, указанные в соединении. Значениями этих параметров будут значения соответствующих полей источника связи.

Далее добавим поле цена в ресурсы и в выбранные поля.

Рис. 5 Вкладка ресурсы

Рис. 6 Выбранные поля

Результат:

Теперь можно формировать отчет. Проверим правильность работы отчета на примере “Дивана для отдыха”.

Рис. 7 Итоговый отчет

В запросе:

По просьбе andreo рассмотрим решение этой же задачи в запросе. Данная задача может быть решена как с использованием вложенных запросов, так и с помощью временных таблиц. Попробуем решить задачу, используя временные таблицы. Сначала приведем весь текст запроса, а потом кратко разберем по частям принцип его работы.

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

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

Данный пакетный запрос содержит три подзапроса. Рассмотрим их подробнее.

Первый запрос пакета группирует данные по периоду, контрагенту и номенклатуре и помещает их во временную таблицу втБезЦены. Далее мы будем соединять эту таблицу с таблицей цен номенклатуры и получим небольшой выигрыш в том, что соединять будем уже сгруппированные данные.

Во втором подзапросе мы соединяем временную таблицу с регистром сведений “ЦеныНоменклатуры” при этом из регистра сведений мы выбираем МАКСИМАЛЬНУЮ дату из меньших или равных дат.  Результат этого подзапроса также помещаем во временную таблицу (втМаксПериод). Посмотрим, какие данные попадают в эту таблицу:

Рис. 8 Временная таблица втМаксПериод

В последнем запросе пакета, мы еще раз соединяем временную таблицу с таблицей цен номенклатуры. На этот мы соединяем таблице по номенклатуре и периоду.

Итоговый результат запроса:

Рис. 9 Итоговый результат запроса

Как мы видим результаты вывода цен в обоих случаях (через СКД и через запрос) оказались одинаковы.

Подписаться
Уведомить о
guest
29 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
andreo
andreo
13 лет назад

Уважаемый also, вы упоминали в начале статьи, что данную задачу можно решить в запросе. Не могли бы вы, дополнив эту статью, или в отдельной статье, описать выполнение срезов на несколько дат в запросе с подробным примером. Заранее спасибо.

EvgeniuXP
EvgeniuXP
13 лет назад

спасибо

ArtDurtuli
ArtDurtuli
13 лет назад

СКД вывести остатки за каждый день?помогите пожалуйста

ArtDurtuli
ArtDurtuli
13 лет назад

Извините вопрос не так задал, как в СКД вывести остатки за каждый день если не было оборотов?

ArtDurtuli
ArtDurtuli
13 лет назад

это я смотрел но он там не пишет как он это сделал,Поставил “период” тип дополнения “месяц” установил дату нач и кон,а он если нет оборота то остатки не выводит

ArtDurtuli
ArtDurtuli
13 лет назад

как это вставить в скд?Там xml код какой то?

ArtDurtuli
ArtDurtuli
13 лет назад

точно ступил

ArtDurtuli
ArtDurtuli
13 лет назад

01.11.2010 0:00:00
01.11.2010 0:00:00
01.11.2010 0:00:00
02.11.2010 0:00:00
03.11.2010 0:00:00
03.11.2010 0:00:00
05.11.2010 0:00:00
05.11.2010 0:00:00
08.11.2010 0:00:00
08.11.2010 0:00:00
09.11.2010 0:00:00
10.11.2010 0:00:00
11.11.2010 0:00:00
12.11.2010 0:00:00
12.11.2010 0:00:00
17.11.2010 0:00:00
18.11.2010 0:00:00
19.11.2010 0:00:00
19.11.2010 0:00:00
22.11.2010 0:00:00
23.11.2010 0:00:00
25.11.2010 0:00:00
25.11.2010 0:00:00
25.11.2010 0:00:00
почти работает,
в периоде некоторых дат не хватает чем это связано

ArtDurtuli
ArtDurtuli
13 лет назад

если не было оборота он не показывает период этот

Игорь Сергеев
Игорь Сергеев
13 лет назад

Можно ли тоже самое провернуть с регистрами остатков?
Пытаюсь соединить ОборотыДС и ОстаткиДС, там чтобы остатки рассчитывались на дату оборотов. Но параметр не срабатывает.

Buliga Alexandru
Buliga Alexandru
13 лет назад

к сожалению выскакивает такая ощибка:
Ошибка обработки представления “РегистрСведений.ЦеныНоменклатуры.СрезПоследних:Несоответствие типов (параметр номер “”1″”)”
<>РегистрСведений.ЦеныНоменклатуры.СрезПоследних(

Buliga Alexandru
Buliga Alexandru
13 лет назад

я в первом наборе присваивал “НачалоПериода” и “КонецПериода” как СтандартныйПериод. Неправильно видимо.

Buliga Alexandru
Buliga Alexandru
13 лет назад

сами наборы те ж как выше в самой статьи.
1. первый набор данных http://tinypic.com/r/2pop8xe/7
2. второй набор http://tinypic.com/r/e84iuv/7
3. и вот связи http://tinypic.com/r/2ldc2lx/7

Petrony
Petrony
13 лет назад

Очень интересная статья. Работа с запросом намного упрощается теперь. Единственное замечание: у меня работает запрос только в случае, если все параметры второго запроса указываются в выборке полей. Если идет связка по параметрам Дата и Номенклатура, то нужно писать:
ВЫБРАТЬ
&Дата КАК Дата,
&Номенклатура КАК Номенклатура,
ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
Что интересно, если пишу ЦеныНоменклатурыСрезПоследних.Номенклатура, то запрос вообще не выдает ничего, в смысле и основной запрос тоже пустой. У меня другой регистр и другие данные, но вряд ли дело в этом.

pmb
pmb
12 лет назад

Пример с СКД интересен.
Интересно имеет ли решение задача получения остатков из регистра накоплений на каждую дату с помощью запроса?

pmb
pmb
12 лет назад

Не совсем понятно зачем при использовании СКД в запросе
ВЫБРАТЬ
&Дата КАК Дата,
ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
{ВЫБРАТЬ
Дата,
Номенклатура.*,
Цена}
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
&Дата,
Номенклатура = &Номенклатура
И ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
{ГДЕ
(&Дата),
ЦеныНоменклатурыСрезПоследних.Номенклатура.*,
ЦеныНоменклатурыСрезПоследних.Цена}
использовать условие
{ГДЕ
(&Дата),
ЦеныНоменклатурыСрезПоследних.Номенклатура.*,
ЦеныНоменклатурыСрезПоследних.Цена}
ведь эти же параметры используется у виртуальной таблицы

Feelthis
Feelthis
12 лет назад

Добрый день, подскажите пожалуйста по моей задаче. Необходимо получать сумму по курсу валюты на каждый день. У меня в регистре 2 записи по ресурсу ВалютнаяСуммаКонечныйОстатокКт:
12.01 10000
12.02 10000
Необходимо выводить курс валюты на каждый день и на 13.01, 14.01 даже если оборотов не было.
У меня получилось вывести курс валют на каждый день – но только когда были обороты. Когда я использую группировку по периоду в настройках отчета и ставлю период дополнения “День” – то СКД не выводит курсы за дни, когда оборотов не было. Помогите пжл как вывести сумму по ресурсу ВалютнаяСуммаКонечныйОстатокКт по курсу за те дни когда оборотов не было
Спасибо

Sergey Vidyakin
Sergey Vidyakin
12 лет назад

Не получается!
Повторил все точь в точь, только без суммы – выдает ошибку про несоответствие первого параметра в регистре во втором наборе данных

Sergey Vidyakin
Sergey Vidyakin
12 лет назад

Блин! Вся фишка в отключении автозаполнения! А у вас это не написано! ((

schwomulurn
schwomulurn
11 лет назад

А у меня такая проблема была, что цена выдавалась самая последняя, то есть параметр Дата не передавался. (Задача: Розница, в отчет по продажам добавить цену по типу цены “Цена Закупки” на дату продажи). Решилась эта проблема также отключением параметра Автозаполнение в запросе-приемнике.