Как сделать срез последних в запросе 1с

Добавил пользователь Алексей Ф.
Обновлено: 04.10.2024


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

превращает платформа 1С примерно в такой запрос:

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

Аналогичные вещи приходится писать и в случае "среза последних на каждую дату в запросе": Классический вариант, Альтернативный и их сравнение.

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

Это был добавлен реквизит регистра сведений с типом "ДатаВремя". Ни в коем случае это поле не должно быть измерением, но вполне могло быть ресурсом, ведь в запросах ресурсы и реквизиты регистра сведений ничем не различимы. Реквизитом, а не ресурсом оно сделано чисто из эстетических принципов )). Зато встроенный механизм виртуальной таблицы "срез последних" нисколько не поврежден и может по-прежнему использоваться.

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

Естественно это поле должно заполняться автоматически. А значит нужно использовать события модуля набора записей ПередЗаписью и ПриЗаписи. Но так как база клиент-серверная в привязке с MS SQL Server, то воспользовались триггерами СУБД After Insert/Update/Delete. Впрочем триггер AfterUpdate был для перестраховки - 1С не изменяет записи регистра сведений, она их удаляет и вставляет заново. Вот пример триггера After Insert.

Индексирование реквизита средствами 1С привело к созданию составного индекса: Период+Все измерения. Помимо этого был добавлен индекс средствами SQL: Период+ПериодОкончания+Период окончания.

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

Аналогичная операция была сделана с курсами валют. Проведены тесты (1000 выполнений запроса) с разными параметрами на запросах:

ЦеныНоменклатурыСрезПоследних.Цена * КурсыВалютСрезПоследних.Курс / ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения.Коэффициент КАК Цена

Срез последних Модификация Экономия времени, %
0,235 0,191 18,72
0,232 0,199 14,22
0,228 0,206 9,65
0,210 0,189 10,00

Замечание 1: срез последних без указания параметра даты, это срез на самую последнюю дату в таблице. У нас это запрос:

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


Замечание 2: все записи считаются активными..
Замечание 3: здесь не рассматривается случай периодичности "позиция регистратора".

В запросе есть конструкция ВЫБРАТЬ ПЕРВЫЕ 1, используя ее и не используя виртуальную таблицу (СрезПоследних), а взяв настоящую (РегистрСведений.ИспользованиеУслуг), отсортировав по периоду в обратном порядке - вы достигните цели!

УПОРЯДОЧИТЬ ПО
Период УБЫВ) КАК ЗапросТариф
ПО Абоненты.Ссылка = ЗапросТариф.Абонент.Ссылка
ГДЕ
Абоненты.ПометкаУдаления = ЛОЖЬ
И Абоненты.ЭтоГруппа = ЛОЖЬ
// ИспользованиеУслугСрезПоследних.Абонент = &абонент

а ничего не выводится потому :

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

РегистрСведений.ЗаказНаряды двигаются и другими документами.

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

РегистрСведений.ЗаказНаряды двигаются и другими документами.

такой запрос не работает (([/quot]

| РегистрСведений.ЗаказНаряды.СрезПоследних(, ЗаказНаряд = ДокЗаказНаряд.Ссылка) КАК ЗН)

Favorite

also Что-то вроде FAQ Отзывов (29) В закладки

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

Первый набор данных:

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

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


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


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

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


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

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

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

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

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

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

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


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

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

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


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


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

Результат:

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


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

В запросе:

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

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

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

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


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

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

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


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

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

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

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

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

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

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

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

Параметры

  • Период (необязательный) - тип: Дата, МоментВремени, Граница. Указывается дата, момент времени или граница, на которые будут получены сведения. Если параметр не задан, будут выбираться наиболее поздние записи, без ограничения по дате.
  • Условие (необязательный) - конструкция языка запросов. Указывается условие на языке запросов. Условие может оперировать полями регистра сведений. Оно будет использовано для ограничения состава записей, среди которых будут выбираться наиболее поздние. То есть условие будет применяться к исходным записям, а не к уже отобранным. Если параметр не задан, анализируются все активные записи регистра.

Срез первых

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


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

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

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

Параметры

  • Период (необязательный) - тип: Дата, МоментВремени, Граница. Указывается дата, момент времени или граница, на которые будут получены сведения. Если параметр не задан, будут выбираться наиболее ранние записи, без ограничения по дате.
  • Условие (необязательный) - конструкция языка запросов. Указывается условие на языке запросов. Условие может оперировать полями регистра сведений. Оно будет использовано для ограничения состава записей, среди которых будут выбираться наиболее ранние. То есть условие будет применяться к исходным записям, а не к уже отобранным. Если параметр не задан, анализируются все активные записи регистра.

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

Читайте также: