Особенность получения среза последних записей в регистре сведений. Особенность получения среза последних записей в регистре сведений Срез последних на дату показывает несколько элементов

Особенность получения среза последних записей в регистре сведений. Особенность получения среза последних записей в регистре сведений Срез последних на дату показывает несколько элементов

Иногда требуется запросом получить из периодического регистра сведений данные на несколько дат сразу. Типичный пример — работа с курсами валют. Рассмотрим алгоритм решение данной задачи на примере.

Постановка задачи

В базе создан документ «РеализацияТоваровУслуг», в шапке которого есть реквизит «Валюта». Запросом требуется для каждого документа получить актуальный курс валюты из шапки на дату документа. Хранение курсов валют осуществляется в периодическом регистре сведений «КурсыВалют «.
Решением «в лоб» этой задачи мог бы быть запрос в цикле: получение всех документов с их датами и валютой и в выборке обращение к виртуальной таблице среза последних регистра «КурсыВалют». Но т.к. запрос в цикле — это «плохо», попробуем реализовать задачу одним запросом .

Решение

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

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

Порядок действий в запросе:

  1. Получение для каждого документа периода установки курса валюты. Документы соединяются с ФИЗИЧЕСКОЙ таблицей «КурсыВалют». Здесь следует обратить внимание на условия соединения. Валюты должны быть равны, а дата документа >= периоду регистра сведений.
    В результате такого соединения для каждого документа будет получено множество строк, удовлетворяющих условию: все записи курсов по валюте документа, установленные не позже даты документа.
    Завершающим этапом будет группировка строк с получением максимального периода курса. В результате для каждого документа будет получен требуемый период установки курса для нужной валюты (максимальная дата установки курса валюты, но не больше даты документа). Результат помещается во временную таблицу ВТПериодыУстановкиКурсов.
  2. Получение курса. Временная таблица ВТПериодыУстановкиКурсов соединяется с ФИЗИЧЕСКОЙ таблицей «КурсыВалют». Соединение происходит по Валюте документа и периоду установки курса, определенному во второй временной таблице.

Предположим, что нам поступила задача, по которой заказчик хочет получить отчет по введенным в базу документам "Реализация товаров и услуг", причем на каждый документ необходимо получать цену из регистра сведений "Цены номенклатуры" на дату документа. Отчет пишется для конфигурации "Управление производственным предприятием" версии 1.3.

К записи из таблицы документа присоединяется запись из виртуальной таблицы "ЦеныНоменклатуры.СрезПоследний" по соответствующим условиям периода, типа цены и номенклатуры. Тип цены получаем из одноименного реквизита документа.

Задача имеет несколько способов решения. Рассмотрим два из них: отчет на СКД с помощью двух наборов данных и получение всех необходимых данных в одном запросе. Теперь по порядку.

Использование СКД

Для реализации подобного отчета на СКД создадим в схеме компоновки данных два набора данных. Первый будет получать список документов, второй цены на даты документов по выбранной номенклатуре и типу цен. Связь между двумя наборами данных осуществляется по номенклатуре, периоду (дата документа) и типу цены. Из первого набора необходимо передвать параметры "Номенклатура", "ТипЦены" и "Период" во второй набор.

Первый набор данных содержит следующий запрос:

Запрос выбирает из таблицы документа и табличной части "Товары" поля: "Ссылка", "Дата", "ТипЦен", "Номенклатура". Теперь рассмотрим второй набор данных:

Во втором наборе данных следует обратить внимание на параметры, передаваемые в запрос. В списке выбираемых полей содержатся параметры "Период, "Номенклатура" и "ТипЦены". Эти же параметры используются в параметрах виртуальной таблицы "ЦеныНоменклатуры.СрезПоследних". Выводить данные параметры в список выбираемых полей необходимо, чтобы из первого набора можно было передавать значения этих параметров во второй набор. Осуществляется это с помощью настроек соединения между наборами данных в вкладке конструктора схемы компоновки данных "Связи наборов данных". Перейдем к ее рассмотрению:

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

Настроив структуру отчета и сформировав его, мы получим следующий результат:

Отчет работает. Перейдем к рассмотрению варианты получения цены на дату документа в одном запросе.

В одном запросе

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

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

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

Результат выполнения аналогичен результату предыдущего отчета (см. скриншот выше).

Делайте выводы

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

Также стоит помнить, что создание отчетов на основе таблиц документов не рекомендуется методикой разработки от фирмы 1С, так как считается, что информация в документах может быть не достоверной. Все отчеты необходимо строить на основании регистров.

В тестовой конфигурации у нас есть периодический регистр сведений "ЦеныНоменклатуры" со следующими исходными данными:

На рисунке представлена также структура метаданных регистра. Как мы видим, регистр содержит измерение "Товар" с типом ссылки на справочник "Товары", а также числовой ресурс "Цена" и реквизит "СтараяЦена".

Допустим, в отчете нам нужно получить срез последних записей для товаров и их цен с условием, что старая цена меньше или равно 50.

Два варианта запроса

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

Запрос = Новый Запрос; Запрос. Текст = " ВЫБРАТЬ | | | | |ИЗ | РегистрСведений. ЦеныНоменклатуры. СрезПоследних КАК ЦеныНоменклатурыСрезПоследних |ГДЕ | ЦеныНоменклатурыСрезПоследних. СтараяЦена < = 50 " ;

Обратите внимание на условие в секции "ГДЕ". В этом и заключается главная ошибка! Этот запрос не вернет ни одной записи, и вот почему: при использовании виртуальных таблиц, в нашем случае "СрезПоследних", сначала выполняется выборка данных из базы по условиям, описанным в виртуальной таблице, а затем выполняются действия, описанные в тексте запроса (группировки, условия в секции "ГДЕ", сортировка и т.д.).

Поэтому в нашем примере запрос и не возвращает результат. Сначала он получает срез последних, а уже после устанавливает условие на реквизит "СтараяЦена". Вот так это выглядит на схеме:

Чтобы правильно решить задачу, условие на реквизит "СтараяЦена" нужно перенести в условия виртуальной таблицы. Вот так будет выглядеть правильный текст запроса:

Запрос = Новый Запрос; Запрос. Текст = " ВЫБРАТЬ ЦеныНоменклатурыСрезПоследних. Период, ЦеныНоменклатурыСрезПоследних. Товар, ЦеныНоменклатурыСрезПоследних. Цена, ЦеныНоменклатурыСрезПоследних. СтараяЦена ИЗ РегистрСведений. ЦеныНоменклатуры. СрезПоследних(, СтараяЦена < = 50 ) КАК ЦеныНоменклатурыСрезПоследних "

Теперь запрос получит правильные данные, поскольку срез последних цен будет получать уже с учетом условия по реквизиту "СтараяЦена".

Результаты

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

Отсюда также вытекает главное правило по использованию виртуальных таблиц: "используя виртуальную таблицу обязательно устанавливайте параметры отбора непосредственно в виртуальной таблице, иначе запрос будет получать излишние данные, на которые уже потом будут устанавливаться отборы".

: СрезПервых и СрезПоследних Рассмотрим работу с этими виртуальными таблицами с использованием 1С. Гораздо чаще применяется СрезПоследних , поэтому с него и начнем.

Срез последних позволяет получить последнюю запись регистра сведений на указанную дату в разрезе измерений. Для таблицы среза последних(первых) есть возможность в скобках указать два параметра через запятую. В первом параметре передается дата на которую делается срез (если параметр не указан срез делается на текущую дату). Второй параметр представляет из себя условие на языке запросов 1С и позволяет устанавливать различные отборы. Как правило в этих отборах используются измерения. Все это звучит достаточно туманно, поэтому без примера никак не обойтись.
Итак пусть у нас есть периодический регистр сведений Цена в котором храняться цены в разрезе товаров и поставщиков. Периодичность регистра — день.

В регистре имеются следующие записи

Для начала получим срез последних без использования параметров выполнив вот такой запрос

ВЫБРАТЬ ЦенаСрезПоследних.Период КАК Период, ЦенаСрезПоследних.Товар КАК Товар, ЦенаСрезПоследних.Поставщик КАК Поставщик, ЦенаСрезПоследних.Сумма КАК Сумма ИЗ РегистрСведений.Цена.СрезПоследних КАК ЦенаСрезПоследних

Так как параметры не указаны срез выполняется на текущую дату - 01.02.2017. В результате получаем вот такую таблицу

Здесь мы видим, что комбинация измерений Товар + Поставщик уникальна, т.е. для каждой комбинации измерений регистра была взята запись с максимальной датой, и дата записи меньше или равна текущей дате.

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

ИЗ РегистрСведений.Цена.СрезПоследних(&ДатаСреза,) КАК ЦенаСрезПоследних

Перед выполнением запроса в него конечно же надо передать параметр &ДатаСреза . Теперь результат запроса будет выглядеть так

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

ИЗ РегистрСведений.Цена.СрезПоследних(&ДатаСреза, Товар = &Товар И Поставщик = &Поставщик) КАК ЦенаСрезПоследних

В итоге получим только одну запись

Чтобы не запутаться во всех этих скобочках и запятых, лучше воспользоваться конструктором запросов. Покажу на примере последнего запроса.

После выбора в конструкторе запроса таблицы со срезом последних необходимо нажать на кнопку Параметры виртуальной таблицы и в открывшемся окне прописать

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


Самое обсуждаемое
Радио мобильного устройства представляет собой встроенный FM-приемник Радио мобильного устройства представляет собой встроенный FM-приемник
Android на большом экране: обзор Sony Ericsson XPERIA X10 Android на большом экране: обзор Sony Ericsson XPERIA X10
Скачать Гаджеты для Windows Скачать Гаджеты для Windows


top