Регистр сведений срез последних реквизиты

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

Срез последних можно получить несколькими способами:

  • При помощи метода СрезПоследних менеджера регистра сведений;
  • При помощи запроса;

Получить срез последних на дату при помощи метода СрезПоследних

Рассмотрим на примере получение среза на дату по регистру ЦеныНоменклатуры, по конкретной заданной номенклатуре при помощи метода СрезПоследних.

Синтаксис метода:

ТЗ = РегистрыСведений.ИмяРегистраСведений.СрезПоследних(<КонецПериода>, <Отбор>);
  • КонецПериода — дата на которую делается срез;
  • Отбор — структура с отбором по измерениям регистра;

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

Пример. Пусть в переменной Номенклатура хранится позиция номенклатуры по которой необходимо получить данные, а в переменной Дата хранится дата на которую необходимо получить цены. Данный пример подходит для конфигурации Бухгалтерия (ред. 2.0 / 3.0).

Отбор = Новый Структура("Номенклатура", Номенклатура);
ТаблицаЦен = РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(Дата, Отбор);

ШаблонСообщения = "Тип цен: %1 Цена: %2";
Для Каждого СтрокаТаблицы Из ТаблицаЦен Цикл

      ТекстСообщения = СтрШаблон(ШаблонСообщения, 
                                 СтрокаТаблицы.ТипЦен, 
                                 СтрокаТаблицы.Цена);
      Сообщить(ТекстСообщения);  
   
КонецЦикла;

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

Рассмотрим пример среза последних по регистру сведений в запросе. Для примера возьмем регистр ЦеныНоменклатуры из конфигурации Бухгалтерия (ред. 2.0 / 3.0). В запросе будем использовать виртуальную таблицу СрезПоследних нужного регистра. В первый параметр таблицы передается дата, на которую необходим срез, во втором можно задать произвольное условие для полей регистра.

Пример 2:

Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ДатаСреза", КонецМесяца(ТекущаяДата()));

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

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

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

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

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

Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Конец",  КонецПериода); 
Запрос.УстановитьПараметр("Начало", НачалоПериода); 
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);

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

Вкратце принцип действия данного механизма следующий:

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

Если хотите подробней узнать о периодических регистрах сведений зайдите на сайт 1С:ИТС


Время на прочтение
6 мин

Количество просмотров 4.7K

Основная трудность, с которой сталкиваются начинающие изучать 1С, заключается в том, что быстро разобраться что здесь к чему очень сложно. В платформе 1С:Предприятие вводится целый ряд оригинальных понятий. Объяснений этих понятий во встроенной справке, на сайте 1С и на прочих ресурсах много, но они мало что проясняют даже искушенному в ИТ. Здесь я расскажу об одном важном понятии в 1С. Простыми словами и со смыслом.

Определение

Приведу для начала две цитаты.

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

Это из встроенной справки. Ее еще называют синтакс-помощник. Слова тут простые, но если смотреть свежим взглядом, лишены какого-либо смысла. Есть регистр, который хранит существенную информацию? А что, есть регистр, который хранит чепуху? Что означает «развернутость» информации? Она была «свернута», а потом «развернулась»? Хотелось бы понять детали этого процесса!

Регистры сведений — это прикладные объекты конфигурации. Они позволяют хранить в прикладном решении произвольные данные в разрезе нескольких измерений.

А это с сайта 1С https://v8.1c.ru/platforma/registr-svedeniy/ Как можно что-то «хранить в разрезе»? Что тут «режется» и зачем?

Мое определение понятия «регистр сведений» звучит так.

Регистр сведений — это полный аналог таблицы базы данных.

Для тех, кто хоть немного знаком с базами данных, будет достаточно следующего дополнения.

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

Для тех, кто не знаком с теорией баз данных поясню, по возможности коротко и просто.

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

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

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

Регистр сведений в платформе 1С:Предприятие позволяет явным образом указать ключ (его еще называют первичный ключ). Этим он и отличается от всех прочих объектов. Для них первичные ключи создаются автоматически и не подлежат изменению.

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

Регистр сведений со множеством измерений

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

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

Один пример я уже дал выше. Еще несколько примеров:

  • цены товаров у поставщиков;

  • подразделение и занимаемая должность работника;

  • место хранения товара на складе;

  • настройки заполнения банковских выписок;

  • график работы сотрудника.

Регистр сведений с одним измерением

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

Конечно, такая практика приводит к некоторой путанице. Открываешь справочник(документ) в режиме пользователя, вот он реквизит. Можно редактировать. Открываешь справочник(документ) в Конфигураторе, нет реквизита! Ищи в другом месте. Но есть и плюс, который заключается в том, что исходный справочник(документ) остается в неизменном виде. И если возникает именно такая задача (внести изменения, но не «трогать» исходный справочник или документ), тогда используют регистр сведений с одним измерением.

Регистр сведений без «измерений»

Можно создать регистр сведений вообще без измерений. Это не будет означать, что у регистра сведений нет ключа вообще и можно вводить сколько угодно записей. Это будет означать, что ключ есть, он представляет собой пустое значение и запись в таблице может быть только одна. В 1С:предприятие есть такой объект, который называется константа. Он не имеет ничего общего с тем, что под этим обычно подразумевается. Концептуально, константа в 1С — это таблица с одной колонкой и одной строкой. Чисто умозрительно, полезная штука, но на практике — не очень. Эти самые константы надо как-то группировать. Приходится задавать префиксы имен. Имена становятся уродливыми. Регистр сведений без измерений, по сути, представляет собой поименованное множество пар ключ-значение. И это отличная альтернатива константам.

Подчинение регистратору

Регистры сведений входят в семейство регистров 1С. По правде сказать, они не совсем полноправные члены этой семьи. Регистры сведений — это универсальный инструмент, в то время как регистры накопления гораздо более специализированы, а уж регистры бухгалтерии и регистры расчетов специализированы очень сильно. Единственное, что обнаруживает родственную связь регистров сведений с прочими регистрами, это то, что записи в регистрах сведений могут создаваться на основании документов. Здесь же, кстати, можно увидеть и отличие регистров сведений от остальных регистров. Во всех прочих регистрах записи создаются ТОЛЬКО на основании документов, а для регистров сведений этот вопрос оставлен на усмотрение разработчика. В принципе, этим пользуются и в типовых и в нетиповых конфигурациях, но лично я не вижу в этом большого смысла. Здесь имеет место скорее некоторая инерция. Разработчики привыкают использовать связку документ-регистр для регистров накопления, а потом переносят эту практику на регистры сведений.

Регистр сведений с измерением типа дата

Есть такая довольно часто встречающаяся задача, которая называется «Получить последние значения чего-либо». У нее есть известное решение, укладывающееся в три строки SQL запроса. В 1С-овском диалекте это выглядит так:

ВЫБРАТЬ валюта, курс, дата
ИЗ РегистрСведений.КурсыВалют КАК КурсыВалют
ГДЕ дата В (ВЫБРАТЬ МАКСИМУМ(дата) ИЗ КурсыВалют КАК Т ГДЕ Т.Валюта = КурсыВалют.Валюта)

Чтобы избавить разработчиков от необходимости вспоминать это решение, в 1С решили сделать так. Регистры сведений, у которых в составе первичного ключа есть дата, были объявлены особенным подвидом и названы периодическими регистрами сведений. У этих периодических регистров сведений появились виртуальные таблицы под названием срез последних. При обращении к этим таблицам происходит выполнение запроса, являющегося аналогом того, что я указал выше. Там, правда, действует странное ограничение. Получить последние значения вы можете только по полному списку измерений. Это противоречит опыту, который разработчики получают при взаимодействии с регистрами накопления. Обращение к виртуальной таблице оборотов регистра накопления возможно по любому подмножеству измерений. Но в целом, периодические регистры сведений — это полезный инструмент. Хотя, в последнее время, с появлением версионирования и истории версий, он несколько утратил свое значение.

Заключение

Сильная сторона 1С в том, что можно не знать многие вещи, например, о базах данных. И при этом создавать работоспособные приложения. В большинстве случаев, вам не требуется знать или помнить в деталях для чего нужны первичные ключи и как они работают. Система все сделает за вас. Но когда вам потребуется сделать что-то из области универсального, тогда начальные знания о том, как это работает, все-таки будут нелишними.

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

  • Подробнее о бесплатном вебинаре

Периодические регистры сведений

Многие программисты, знакомые с версией 7.7 и желающие освоить версию 8, спрашивают, куда делись периодические реквизиты справочников и периодические константы. А если их нет, то какой механизм их заменяет? В 1С:Предприятии 8 для хранения истории изменения значений предназначены периодические регистры сведений.

Вообще регистры сведений предназначены для хранения информации, развернутой по комбинации измерений. Главное отличие периодического регистра сведений от обычного заключается в том, что в нем присутствует дополнительное системное измерение «Период», имеющее тип «дата». Это позволяет получать не только текущие сведения об объекте, но также на любой момент времени.

Для периодического реквизита при создании указывается свойство «Периодичность» из следующих возможных значений:

  • в пределах секунды,
  • в пределах дня,
  • в пределах месяца,
  • в пределах квартала,
  • в пределах года,
  • по позиции регистратора (доступен, если режим записи у регистра — «Подчинение регистратору»).

Обратите внимание, что тип ресурса сведений может быть как примитивный (число, строка, дата, булево), так и ссылочный (СправочникСсылка, ДокументСсылка, ПеречислениеСсылка и т.д.). Более того, в регистре сведений можно хранить даже картинки и другие неструктурированные сведения, поскольку можно создать ресурс типа «ХранилищеЗначения».

Самый простой пример периодического регистра сведений — КурсыВалют. Этот регистр сведений хранит курсы всех валют на каждый день. Структура регистра представлена ниже:

Подробная информация о структуре регистра сведений КурсыВалют приведена в следующей таблице:

Измерения: Валюты тип «СправочникСсылка.Валюты», ведущее, запрет незаполненных значений
Ресурсы: тип «число», длина 15, точность 4, неотрицательное
тип «число», длина 10, точность 0, неотрицательное
Периодичность В пределах дня
Режим записи Независимый

Данные в этот регистр сведений можно вводить вручную с помощью формы списка.

ВНИМАНИЕ. В регистр сведений с определенной периодичностью, не равной «По позиции регистратору», нельзя ввести две записи с одинаковым набором измерений и периодом, т.е. нельзя ввести два курса одной валюты в один день. Если периодичность записи регистра имеет значение «По позиции регистратора», то ключ уникальности записи также содержит и ссылку на документ-регистратор, т.е. в таком регистре не может существовать две записи с одинаковым набором измерений, периодом и регистратором. Это неотъемлемое свойство регистра сведений, отличающее его от остальных регистров.

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

Обращение к периодическим сведениям с помощью методов

Объект РегистрСведенийМенеджер позволяет обращаться к «итогам» регистра. Под «итогами» периодического регистра сведений понимаются первые или последние значения ресурсов по указанным измерениям. При этом применяются следующие методы:

Возвращает в виде структуры значения ресурсов одной записи регистра, соответствующей указанным значениям всех (!) измерений регистра и периоду.

ПолучитьПоследнее (<Конец периода>, <Отбор>)

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

ПолучитьПервое (<Начало периода>, <Отбор>)

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

СрезПоследних (<Конец периода>, <Отбор>)

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

СрезПервых (<Начало периода>, <Отбор>)

При вызове методов ПолучитьПервое, ПолучитьПоследнее, СрезПервых и СрезПоследних первый параметр может иметь тип «дата», МоментВремени или Граница, но его можно вообще не указывать, тогда будут найдены значения ресурсов из самой первой или последней записи регистра соответственно.

Продемонстрируем использование этих методов на примерах:

Пример 1. Получение курса валюты точно на заданную дату (если записи именно на эту дату нет, то в элементах структуры будут пустые значения).

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

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

Пример 4. Получение актуальных оптовых цен на товары (указан отбор по измерению «ТипЦен»)

Обращение к периодическим сведениям с помощью запросов

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

Метод Описание
Поле Описание
<Имя измерения> Набор полей, содержащий значения измерений регистра. Имена полей соответствуют именам измерений.
<Имя реквизита> Набор полей, содержащий значения реквизитов регистра.
<Имя ресурса> Набор полей, который содержит значения ресурсов регистра.
Активность Содержит признак активности записи. Записи, для которых значение данного свойства установлено в Ложь, не будут учитываться при получении «первых» или «последних» записей регистра, а также при получении сведений на определенный момент времени.
МоментВремени Содержит момент времени записи регистра.
НомерСтроки Содержит номер строки, определяемый как порядковый номер записи в наборе записей.
Период Содержит период, к которому относится запись регистра.
Регистратор Содержит ссылку на документ-регистратор движения.

При обращении к виртуальным таблицам СрезПервых и СрезПоследних можно указать следующие параметры:

Параметр Описание
Дата Указывается дата или момент времени, на которые будут получены сведения. Если параметр не задан, будут выбираться наиболее поздние/ранние записи.
Условие Указывается условие на языке запросов. Оно будет использовано для ограничения состава записей, среди которых будут выбираться наиболее поздние/ранние. Условие будет применяться к исходным записям, а не к уже отобранным.

Приведем примеры обращения к записям регистра сведений с помощью запросов:

Пример 1. Выбрать все записи регистра сведений

Пример 2. Получить актуальный курс одной валюты на заданную дату

Пример 3. Выбрать актуальные курсы всех валют на заданную дату

Пример 4. Получить актуальный прайс-лист на заданную дату (указан определенный тип цен, например, «Розничная»)

Срез последних

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

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


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

Период Товар Поставщик Сумма
01.01.2017 Карандаш ООО «Леспром» 10
25.01.2017 Карандаш ООО «Леспром» 15
01.01.2017 Карандаш ПАО «Канцтовары» 27
01.02.2017 Карандаш ПАО «Канцтовары» 31
03.01.2017 Ручка ПАО «Канцтовары» 137
01.02.2017 Ручка ПАО «Канцтовары» 145

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

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

Период Товар Поставщик Сумма
25.01.2017 Карандаш ООО «Леспром» 15
01.02.2017 Карандаш ПАО «Канцтовары» 31
01.02.2017 Ручка ПАО «Канцтовары» 145

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

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

Период Товар Поставщик Сумма
01.01.2017 Карандаш ООО «Леспром» 10
01.01.2017 Карандаш ПАО «Канцтовары» 27
03.01.2017 Ручка ПАО «Канцтовары» 137

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

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

Период Товар Поставщик Сумма
01.01.2017 Карандаш ПАО «Канцтовары» 27

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

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

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

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

Изображение

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

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

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

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

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

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

Изображение

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

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

Изображение

Результаты

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

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

Вступайте в мою группу помощник программиста.
В ней мы обсуждаем программирование в 1С.

/// Как прочитать записи регистра сведений
/// в 1с 8.3, 8.2
 
&НаСервере
Процедура КакПрочитатьЗаписиРегистраСведенийНаСервере()
 
    // Прочитаем все записи регистра сведений "ЦенаНаЕдуДляКлиентов"
    // для организации ООО "Ромашка", упорядоченные по дате.
 
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ЦенаНаЕдуДляКлиентов.Период,
        |   ЦенаНаЕдуДляКлиентов.Регистратор,
        |   ЦенаНаЕдуДляКлиентов.НомерСтроки,
        |   ЦенаНаЕдуДляКлиентов.Активность,
        |   ЦенаНаЕдуДляКлиентов.Номенклатура,
        |   ЦенаНаЕдуДляКлиентов.Контрагент,
        |   ЦенаНаЕдуДляКлиентов.Организация,
        |   ЦенаНаЕдуДляКлиентов.Цена
        |ИЗ
        |   РегистрСведений.ЦенаНаЕдуДляКлиентов КАК ЦенаНаЕдуДляКлиентов
        |ГДЕ
        |   ЦенаНаЕдуДляКлиентов.Активность = Истина И
        |   ЦенаНаЕдуДляКлиентов.Организация = &ВыбОрганизация
        |УПОРЯДОЧИТЬ ПО
        |   ЦенаНаЕдуДляКлиентов.Период";
 
    Запрос.УстановитьПараметр(
        "ВыбОрганизация",
        Справочники.Организации.НайтиПоНаименованию("ООО ""Ромашка""")
    );
 
    РезультатЗапроса = Запрос.Выполнить();
 
    Записи = РезультатЗапроса.Выбрать();
 
    Пока Записи.Следующий() Цикл
 
        Сообщить(
            "[" + Записи.Период + "] " +
            Записи.Контрагент + " " +
            Записи.Номенклатура + " " +
            Записи.Цена + " руб."
        );
 
    КонецЦикла;
 
КонецПроцедуры
 
/// Как получить наиболее поздние записи (срез последних)
/// регистра сведений на указанную дату (включительно)
/// в 1с 8.3, 8.2
 
&НаСервере
Процедура КакПолучитьНаиболееПоздниеЗаписиРегистраСведенийНаСервере()
 
    // За возможности выборки наиболее поздних записей регистра
    // сведений (среза последних) в разрезе заданной аналитики
    // отвечает виртуальная таблица СрезПоследних.
    // У неё есть следующие параметры:
    // 1. Период (включительно)
    // 2. Условие (например, Организация = &ВыбОрганизация)    
 
    // Получим цены на бананы для каждого контрагента
    // на конец 1 квартала 2014 года (включительно)
    // по организации ООО "Ромашка".
 
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Период,
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Активность,
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Номенклатура,
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Контрагент,
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Организация,
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Цена
        |ИЗ
        |   РегистрСведений.ЦенаНаЕдуДляКлиентов.СрезПоследних(
        |       ДАТАВРЕМЯ(2014, 03, 31, 23, 59, 59),
        |       Активность = Истина И
        |       Организация = &ВыбОрганизация И
        |       Номенклатура = &ВыбНоменклатура
        |   ) КАК ЦенаНаЕдуДляКлиентовСрезПоследних
        |УПОРЯДОЧИТЬ ПО
        |   ЦенаНаЕдуДляКлиентовСрезПоследних.Контрагент";
 
    Запрос.УстановитьПараметр("ВыбОрганизация",
        Справочники.Организации.НайтиПоНаименованию("ООО ""Ромашка""")
    );
    Запрос.УстановитьПараметр("ВыбНоменклатура",
        Справочники.Номенклатура.НайтиПоНаименованию("Банан")
    );
 
    РезультатЗапроса = Запрос.Выполнить();
 
    Записи = РезультатЗапроса.Выбрать();
 
    Пока Записи.Следующий() Цикл
        Сообщить(
            "[" + Записи.Контрагент + ", " + Записи.Период + "] " +            
            Записи.Номенклатура + " " +
            Записи.Цена + " руб."
        );
    КонецЦикла;
 
КонецПроцедуры
 
/// Как получить наиболее ранние записи (срез первых)
/// регистра сведений на указанную дату (включительно)
/// в 1с 8.3, 8.2
 
&НаСервере
Процедура КакПрочитатьНаиболееРанниеЗаписиРегистраСведенийНаСервере()    
 
    // За возможности выборки наиболее ранних записей регистра
    // сведений (среза первых) в разрезе заданной аналитики
    // отвечает виртуальная таблица СрезПервых.
    // У неё есть следующие параметры:
    // 1. Период (включительно)
    // 2. Условие (например, Организация = &ВыбОрганизация)    
 
    // ! Нужно внимательно вдуматься. СрезПервых получает по каждой
    // комбинации измерений наиболее раннюю запись, но НЕ БОЛЕЕ
    // РАННЮЮ, чем указанная дата.    
 
    // Получим самые первые цены, которые были установлены на бананы
    // для каждого контрагента в 2014 году (включительно)
    // по организации ООО "Ромашка".
 
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Период,
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Активность,
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Номенклатура,
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Контрагент,
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Организация,
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Цена
        |ИЗ
        |   РегистрСведений.ЦенаНаЕдуДляКлиентов.СрезПервых(
        |       ДАТАВРЕМЯ(2014, 01, 01, 00, 00, 00),
        |       Активность = Истина И
        |       Организация = &ВыбОрганизация И
        |       Номенклатура = &ВыбНоменклатура
        |   ) КАК ЦенаНаЕдуДляКлиентовСрезПервых
        |УПОРЯДОЧИТЬ ПО
        |   ЦенаНаЕдуДляКлиентовСрезПервых.Контрагент";
 
    Запрос.УстановитьПараметр("ВыбОрганизация",
        Справочники.Организации.НайтиПоНаименованию("ООО ""Ромашка""")
    );
    Запрос.УстановитьПараметр("ВыбНоменклатура",
        Справочники.Номенклатура.НайтиПоНаименованию("Банан")
    );
 
    РезультатЗапроса = Запрос.Выполнить();
 
    Записи = РезультатЗапроса.Выбрать();
 
    Пока Записи.Следующий() Цикл
        Сообщить(
            "[" + Записи.Контрагент + ", " + Записи.Период + "] " +
            Записи.Номенклатура + " " +
            Записи.Цена + " руб."
        );
    КонецЦикла;
 
КонецПроцедуры
 
/// Как найти и изменить програмно записи в регистр сведений
/// документа в 1с 8.3, 8.2
 
&НаСервере
Процедура КакНайтиИИзменитьЗаписиДокументаНаСервере()
 
    // Предположим, у нас есть ссылка на проведенный документ
    // "Установка цен на еду" № ВМБП-000001
 
    УстановкаЦенСсылка =
        Документы.УстановкаЦенНаЕдуДляКлиентов.НайтиПоНомеру(
            "ВМБП-000001", '20141231'
        );
 
    // Мы знаем, что этот документ делает записи в регистр
    // сведений "ЦенаНаЕдуДляКлиентов":
    // [Организация, Контрагент, Номенклатура] [Цена]
 
    // Наша задача: найти эти записи и изменит их (например, удвоим
    // цену) и записать вместо старых.
 
    // Используем объектную технику получения записей,
    // ведь мы будем их изменять.
 
    УстановкаЦен = УстановкаЦенСсылка.ПолучитьОбъект();
 
    // Получим набор записей этого документа в регистр
    // "ЦенаНаЕдуДляКлиентов"
 
    НаборЗаписей = УстановкаЦен.Движения.ЦенаНаЕдуДляКлиентов;
 
    // Прочитаем записи из базы данных.
 
    НаборЗаписей.Прочитать();
 
    Для Каждого Запись Из НаборЗаписей Цикл
 
        // Выведем старые значения.
        Сообщить(
            "[" + Запись.Организация + ", " +
            Запись.Контрагент + ", " + 
            Запись.Номенклатура + "] " +
            "[" + Запись.Цена + "]"
        );
 
        Запись.Цена = Запись.Цена * 2;
 
    КонецЦикла;
 
    // Добавим новую запись.
 
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Период = ТекущаяДата();
    НоваяЗапись.Организация = 
        Справочники.Организации.НайтиПоНаименованию("ООО ""Ромашка""");
    НоваяЗапись.Контрагент =
        Справочники.Контрагенты.НайтиПоНаименованию("Петров Ю.В.");
    НоваяЗапись.Номенклатура =
        Справочники.Номенклатура.НайтиПоНаименованию("Банан");
    НоваяЗапись.Цена = 500;    
 
    // Разом запишем набор записей.
    НаборЗаписей.Записать(
        Истина // Удалим старые записи и запишем вместо них новые.
    );
 
    // Теперь записи регистра "ЦенаНаЕдуДляКлиентов" для документа
    // № ВМБП000001, отличаются от тех, что были записаны
    // документом при проведении. Чтобы вернуть их к начальному виду
    // нужно заново провести документ.
 
КонецПроцедуры
 
/// Как прочитать записи документа в регистр сведений запросом
/// в 1с 8.3, 8.2
 
&НаСервере
Процедура КакПрочитатьЗаписиДокументаЗапросомНаСервере()    
 
    // Этот прием используется, если не требуется изменять
    // найденные записи.
 
    // Предположим, у нас есть ссылка на проведенный документ
    // "Установка цен на еду" № ВМБП-000001
 
    УстановкаЦенСсылка =
        Документы.УстановкаЦенНаЕдуДляКлиентов.НайтиПоНомеру(
            "ВМБП-000001", '20141231'
        );
 
    // Мы знаем, что этот документ делает записи в регистр
    // сведений "ЦенаНаЕдуДляКлиентов".
    // Прочитаем эти записи запросом.
 
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ЦенаНаЕдуДляКлиентов.Период,
        |   ЦенаНаЕдуДляКлиентов.Регистратор,
        |   ЦенаНаЕдуДляКлиентов.НомерСтроки,
        |   ЦенаНаЕдуДляКлиентов.Активность,
        |   ЦенаНаЕдуДляКлиентов.Номенклатура,
        |   ЦенаНаЕдуДляКлиентов.Контрагент,
        |   ЦенаНаЕдуДляКлиентов.Организация,
        |   ЦенаНаЕдуДляКлиентов.Цена
        |ИЗ
        |   РегистрСведений.ЦенаНаЕдуДляКлиентов КАК ЦенаНаЕдуДляКлиентов
        |ГДЕ
        |   ЦенаНаЕдуДляКлиентов.Регистратор = &ВыбРегистратор
        |УПОРЯДОЧИТЬ ПО
        |   ЦенаНаЕдуДляКлиентов.НомерСтроки";
 
    Запрос.УстановитьПараметр(
        "ВыбРегистратор",
        УстановкаЦенСсылка
    );
 
    РезультатЗапроса = Запрос.Выполнить();
 
    Записи = РезультатЗапроса.Выбрать();
 
    Пока Записи.Следующий() Цикл
        Сообщить(
            "[" + Записи.Организация + ", " +
            Записи.Контрагент + ", " + 
            Записи.Номенклатура + "] " +
            "[" + Записи.Цена + "] <" +
            Записи.Регистратор + ">"
        );
    КонецЦикла;
 
КонецПроцедуры
 
/// Как создать записи в регистр сведений без привязки к
/// документу в 1с 8.3, 8.2
 
&НаСервере
Процедура КакСоздатьЗаписиБезПривязкиКДокументуНаСервере()
 
    // Создавать записи в регистре сведений без привязки
    // к документу можно только для регистров, у которых
    // выбран режим записи "Независимый". В нашей конфигурации
    // таким регистром является "КурсВалют".    
    // Если бы мы захотели проделать такую же штуку для
    // регистра "ЦенаНаЕдуДляКлиентов", то нам бы пришлось
    // воспользоваться документом "ОперацияБух" или им подобным
    // для ручных операций (см. аналогичный пример в регистрах
    // накопления).
 
    // Пример №1.
 
    // Для единичных записей удобно пользоваться менеджером
    // записей.
 
    НоваяЗапись = РегистрыСведений.КурсВалют.СоздатьМенеджерЗаписи();
    НоваяЗапись.Период = '20140101';
    НоваяЗапись.Валюта = Справочники.Валюты.НайтиПоНаименованию("Доллар");
    НоваяЗапись.Курс = 30;
    НоваяЗапись.Записать(
        Истина // замещать, если уже есть запись с такими же измерениями
        // и таким же периодом
    );
 
    // Пример №2.
 
    // При помощи менеджера можно также легко
    // менять или удалять единичные записи.
    // Найдём, изменим, а затем удалим созданную запись.
 
    Выборка = РегистрыСведений.КурсВалют.Выбрать('20140101', '20140101');
    Если Выборка.Следующий() Тогда
        Запись = Выборка.ПолучитьМенеджерЗаписи();
        // изменим
        Запись.Прочитать();
        Запись.Курс = 25;
        // запишем
        Запись.Записать(Истина);
        // и тут же удалим
        Запись.Удалить();
    КонецЕсли;
 
    // Пример №3.
 
    // Если нужно изменить сразу много записей - 
    // удобнее всего использовать набор записей.
 
    // Запишем курсы валют за первые 3 дня 2014 года.
 
    Доллар = Справочники.Валюты.НайтиПоНаименованию("Доллар");
 
    НаборЗаписей = РегистрыСведений.КурсВалют.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Валюта.Установить(Доллар);    
 
    Запись01 = НаборЗаписей.Добавить();
    Запись01.Период = '20140101';
    Запись01.Валюта = Доллар;
    Запись01.Курс = 30;
 
    Запись02 = НаборЗаписей.Добавить();
    Запись02.Период = '20140102';
    Запись02.Валюта = Доллар;
    Запись02.Курс = 40;
 
    Запись03 = НаборЗаписей.Добавить();
    Запись03.Период = '20140103';
    Запись03.Валюта = Доллар;
    Запись03.Курс = 60;
 
    // Запишем весь набор разом.
 
    НаборЗаписей.Записать(
        Истина // затрём все другие записи по 
        // доллару (мы установили его в отборе)
    );
 
КонецПроцедуры
 
/// Скачать и выполнить эти примеры на компьютере

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

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

Срез последних

Предназначена для получения наиболее поздних записей регистра сведений на указанную дату (включительно) (см. рисунок 1).

Рисунок 1. Примерная схема среза последних

Включает только активные записи. По каждой комбинации измерений будет найдена наиболее поздняя запись, но не более поздняя, чем указанная дата. В режиме совместимости Версия8_3_17 и ниже включает записи независимо от признака активности (да да, с версии 8.3.18 исправили некорректное поведение системы). Является наиболее востребованной виртуальной таблицей, так как задачи получения среза последних встречаются довольно часто.

Поля

  • <Имя измерения> — тип: Произвольный. Набор полей содержит значения измерений регистра. Имена полей соответствуют именам измерений, как они заданы в конфигураторе.
  • <Имя общего реквизита> — тип: Произвольный. Набор таких полей и их наименования определяются набором общих реквизитов, не являющихся разделителями (РазделениеДанных = НеИспользовать), или разделителей с ИспользованиеРазделяемыхДанных = НезависимоИСовместно, в которых участвует данный регистр сведений.
  • <Имя реквизита> — тип: Произвольный. Набор полей содержит значения реквизитов регистра. Имена полей соответствуют именам реквизитов, как они заданы в конфигураторе.
  • <Имя ресурса> — тип: Произвольный. Набор полей содержит значения ресурсов регистра. Имена полей соответствуют именам ресурсов, как они заданы в конфигураторе.
  • Активность — тип: Булево. Содержит признак активности записи и влияния на получение первых и последних записей. Имеет смысл только для регистров, записываемых регистратором.
  • НомерСтроки — тип: Число. Содержит номер строки, определяемый как порядковый номер записи в наборе записей. Имеет смысл только для регистров, записываемых регистратором.
  • Период — тип: Дата. Содержит период, к которому относится запись регистра. Имеет смысл только для периодических регистров.
  • Регистратор — тип: ДокументСсылка.<Имя документа>. Содержит ссылку на документ-регистратор движения. Имеет смысл только для регистров, записываемых регистратором.

Параметры

  • Период (необязательный) — тип: Дата, МоментВремени, Граница. Указывается дата, момент времени или граница, на которые будут получены сведения. Если параметр не задан, будут выбираться наиболее поздние записи, без ограничения по дате.
  • Условие (необязательный) — конструкция языка запросов. Указывается условие на языке запросов. Условие может оперировать полями регистра сведений. Оно будет использовано для ограничения состава записей, среди которых будут выбираться наиболее поздние. То есть условие будет применяться к исходным записям, а не к уже отобранным. Если параметр не задан, анализируются все активные записи регистра.
  
// Выбрать актуальные курсы всех валют на заданную дату
ВЫБРАТЬ
  Валюта,
  Курс 
ИЗ
  РегистрСведений.КурсыВалют.СрезПоследних(&ВыбДата)

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

Срез первых

Предназначена для получения наиболее ранних записей регистра сведений на указанную дату (включительно) (см. рисунок 2).

Рисунок 2. Примерная схема среза первых

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

Поля

  • <Имя измерения> — тип: Произвольный. Набор полей содержит значения измерений регистра. Имена полей соответствуют именам измерений, как они заданы в конфигураторе.
  • <Имя общего реквизита> — тип: Произвольный. Набор таких полей и их наименования определяются набором общих реквизитов, не являющихся разделителями (РазделениеДанных = НеИспользовать), или разделителей с ИспользованиеРазделяемыхДанных = НезависимоИСовместно, в которых участвует данный регистр сведений.
  • <Имя реквизита> — тип: Произвольный. Набор полей содержит значения реквизитов регистра. Имена полей соответствуют именам реквизитов, как они заданы в конфигураторе.
  • <Имя ресурса> — тип: Произвольный. Набор полей содержит значения ресурсов регистра. Имена полей соответствуют именам ресурсов, как они заданы в конфигураторе.
  • Активность — тип: Булево. Содержит признак активности записи и влияния на получение первых и последних записей. Имеет смысл только для регистров, записываемых регистратором.
  • НомерСтроки — тип: Число. Содержит номер строки, определяемый как порядковый номер записи в наборе записей. Имеет смысл только для регистров, записываемых регистратором.
  • Период — тип: Дата. Содержит период, к которому относится запись регистра. Имеет смысл только для периодических регистров.
  • Регистратор — тип: ДокументСсылка.<Имя документа>. Содержит ссылку на документ-регистратор движения. Имеет смысл только для регистров, записываемых регистратором.

Параметры

  • Период (необязательный) — тип: Дата, МоментВремени, Граница. Указывается дата, момент времени или граница, на которые будут получены сведения. Если параметр не задан, будут выбираться наиболее ранние записи, без ограничения по дате.
  • Условие (необязательный) — конструкция языка запросов. Указывается условие на языке запросов. Условие может оперировать полями регистра сведений. Оно будет использовано для ограничения состава записей, среди которых будут выбираться наиболее ранние. То есть условие будет применяться к исходным записям, а не к уже отобранным. Если параметр не задан, анализируются все активные записи регистра.
  
// Получение всех наиболее ранних записей регистра сведений
ВЫБРАТЬ * ИЗ РегистрСведений.КурсВал.СрезПервых()

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

Материал для статьи взят со справки платформы 1С и приведен к удобочитаемому виду.

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

Вот еще несколько интересных статей нашего сайта:

  • Монгольские компании в москве
  • Мондиал бизнес консорциум ооо
  • Монетка реквизиты организации
  • Монополия на большую компанию
  • Монопольные компании в россии

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии