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

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

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

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

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

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

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

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

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

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

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

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

Результаты

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

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

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

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

Итак пусть у нас есть периодический регистр сведений Цена в котором храняться цены в разрезе товаров и поставщиков. Периодичность регистра - день.

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

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

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

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

Период | Товар | Поставщик | Сумма

25.01.2017 | Карандаш | ООО «Леспром» | 15

01.02.2017 | Карандаш | ПАО «Канцтовары» | 31

01.02.2017 | Ручка | ПАО «Канцтовары» | 145

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

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

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

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

Период | Товар | Поставщик | Сумма

01.01.2017 | Карандаш | ООО «Леспром» | 10

01.01.2017 | Карандаш | ПАО «Канцтовары» | 27

03.01.2017 | Ручка | ПАО «Канцтовары» | 137

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

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

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

Период | Товар | Поставщик | Сумма

01.01.2017 | Карандаш | ПАО «Канцтовары» | 27

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

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

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

Скопипастил с: http://www.kb.mista.ru/article.php?id=92

Получение актуальных данных из регистра сведений на дату, получаемую в самом запросе


Существует несколько способов получить нужные данные.

1.Непосредственно в запросе (через реальную таблицу регистра)

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

Вызов СрезПоследних() можно использовать только с передачей в него заранее готового значения даты, на которую требуется получить значения. Поэтому сабж делается через стыковку нескольких запросов -
основной, к нему стыкуется запрос по регистру сведений с условием по дате и поиском записи с маскимальной датой (периодом).

Для общего развития:
Что есть срез последних в платформе?

В зависимости от периодичности регистра (по времени, по позизии регистратора) ВТ разворачивается в следующий запрос:
1. По времени (год, месяц, ... секунда)

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

Все это можно увидеть посмотрев технологический журнал с включенным режимом протоколирования запросов

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

Данный способ подходит для отчетов. Из очевидных плюсов - если курс (или другие данные) не нужны для построения отчета, то СКД не будет их получать. Однако быстродействие такого отчета может оказаться и несколько ниже, чем в первом способе.

Для примера сделаем отчет - список заказов покупателей.

Для этого создадим набор данных "Документы" - запрос:

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

Для того, чтобы получить информацию о курсах валют, добавим второй набор данных-запрос, "Курсы валют":

В этом запросе имеются 2 параметра: "Дата" и "Валюта". Эти параметры будут установлены СКД при соединении наборов. Кроме того, параметр "Дата" указан в выбранных полях - это нужно для соединения таблиц.
Для ненужный полей "Дата" и "Валюта" также устанавливаем флажки ограничений, чтобы они не появлялись в доступных полях.

Перейдем к соединению наборов. На странице "Связи наборов данных" добавим 2 связи:
1. Источник связи - набор "Документы", приемник - набор "Курсы валют". Выражение источник - "Дата", выражение приемник - "Дата", Параметр - "Дата"
2. Источник связи - набор "Документы", приемник - набор "Курсы валют". Выражение источник - "ВалютаДокумента", выражение приемник - "Валюта", Параметр - "Валюта"

Главное здесь - параметры связи. При соединении наборов данных, если указан параметр, СКД передает в подчиненный набор (в нашем случае - запрос "Курсы валют") параметры, указанные в соединении. Значениями параметров будут значения соответствующих полей набора-источника.

Перейдем к вычисляемым полям. Добавим вычисляемое поле "СуммаВВалютеУпрУчета". Выражение поля - "СуммаДокумента * Курс / Кратность".

Также укажем поля "СуммаДокумента" и "СуммаВВалютеУпрУчета" как ресурсы

Настроим отчет.
Добавим одну группировку "Детальные записи", в выбранных полях укажем "ЗаказПолкупателя", "Курс" и "Кратность". Добавим ресурсы "СуммаДокумента" и "СуммаВВалютеУпрУчета"

Можно формировать отчет

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/
Реализация обработки данных

Разрешение итогов для периодических регистров сведений

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

1.1. Для периодических регистров сведений рекомендуется разрешить итоги, если выполнены все следующие условия:

  • в регистре ожидается большой объем данных (например, оправданно для регистра с ценами номенклатуры ; но не имеет смысла для регистра с курсами валют);
  • в конфигурации предусмотрены частотные запросы к срезам последних на текущий момент времени и/или к срезам первых для получения актуальных данных (т.е. когда не задан период в параметрах виртуальных таблиц СрезПервых и СрезПоследних );
  • при этом остальные условия для виртуальных таблиц СрезПервых и СрезПоследних задаются только на значения измерений (и разделителей, находящихся в режиме Независимо и совместно );
  • в ограничениях доступа к данным регистра используются только измерения (и разделители, находящиеся в режиме Независимо и совместно ).

Полный список всех условий, когда в запросах задействуются итоги регистра сведений, см. в документации к платформе 1С:Предприятие .

Например, если в конфигурации предусмотрены часто выполняющиеся запросы к регистру ЦеныНоменклатуры для получения текущих цен номенклатуры:

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

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

1.2. Кроме того, следует рассмотреть альтернативные варианты по пересмотру запросов к регистру таким образом, чтобы эти условия выполнялись.

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

Однако если при открытии формы подбора товаров анализировать, есть ли регистраторы с будущей датой, и если их нет – выполнять другой запрос к срезу последних без установки даты, то такой запрос будет работать быстрее.

2. Во всех остальных случаях, не следует разрешать итоги для периодических регистров сведений. Прежде всего, если

  • чаще всего (всегда) к виртуальным таблицам среза первых/последних периодического регистра сведений выполняются запросы на конкретный период (например, на дату документа).
  • в условиях для виртуальных таблиц СрезПервых и СрезПоследних чаще всего (всегда) используются подзапросы и соединения (обращения «через точку» к полям связанных таблиц). Например, в этом случае:

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

Понравилась статья? Поделиться с друзьями: