← вся теориятеория к собесу · Оптимизация запросов 1С

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

разбор писал Даниил, автор Сеньорчика

Зачем это спрашивают

Срез последних отдаёт значение на дату, и на нём держатся цены и курсы. Условие среза в параметре и в ГДЕ дают разный результат, и на этом валятся даже опытные. Ещё спрашивают, как получить цену на дату каждой строки продаж, раз у среза дата одна. Запросы сверены на PostgreSQL.

// Так спрашивают: «Чем условие в параметре среза отличается от условия в ГДЕ?» «Что вернёт срез последних без даты?» «Как получить цену на дату каждой продажи?» «Чем СрезПервых отличается от СрезПоследних?»

Параметр и ГДЕ у среза

Курсы валют приходят из двух источников, и у записи есть реквизит Источник. Нужны курсы ЦБ на 15 октября. Условие на источник можно поставить в параметр среза или в ГДЕ:

В параметре срез ищет последнюю запись среди записей ЦБ, и доллар получает курс 92 от 1 октября. В ГДЕ срез сначала берёт последнюю запись вообще, для доллара это биржевые 93 от 10 октября, а потом условие отбрасывает её, и доллар исчезает из результата. У остатков и оборотов параметр и ГДЕ дают одно и то же, у среза нет.

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

Граница и срез без даты

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

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

Срез на дату каждой строки

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

Если соединить продажи с ценами по Период <= Дата и не выбрать максимум, продажа 20 октября размножится на две строки, по каждой прошлой цене, и сумма отчёта удвоится. Первый шаг с МАКСИМУМ оставляет ровно одну цену на продажу.

На больших регистрах цен срез текущих значений ускоряет свойство «Разрешить итоги: срез последних»: платформа держит таблицу последних значений и читает её напрямую.

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

Как отвечать: «Курсы ЦБ на дату: условие на источник поставишь в параметр среза или в ГДЕ?»

В параметр. Тогда срез ищет последнюю запись среди записей ЦБ, и каждая валюта получит последний курс ЦБ. Если поставить условие в ГДЕ, срез сначала возьмёт последнюю запись по валюте из любого источника, и если она биржевая, условие её отбросит, и валюта пропадёт целиком. У остатков и оборотов разницы в результате нет, а у среза она принципиальная.

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

На чём валят

  • −Ставят условие на реквизит после среза в ГДЕ. Пропадают ключи, у которых последняя запись «не та». Условие ставят в параметр.
  • −Ждут, что срез на дату не увидит запись ровно на эту дату. Граница включена, запись на дату попадает.
  • −Берут текущую цену срезом без даты. Попадут цены, заведённые на будущее. Дату передают явно.
  • −Соединяют продажи с ценами по Период <= Дата без максимума. Продажа размножится на все прошлые цены. Сначала МАКСИМУМ(Период), потом соединение.

Проверь себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #oc_vt_slices1 / 5
    Запись в регистр цен сделана с периодом ровно &Дата. Попадёт ли она в СрезПоследних(&Дата)?
    A)Нет, строго раньше
    B)Да: период не позже даты среза
    C)Только если время записи 00:00:00
    D)Только для периодичности «День»
    показать ответ и разбор
    +B)Да: период не позже даты среза

    // разбор: Срез последних отбирает записи с периодом меньше или равным дате среза, поэтому запись ровно на эту дату в него попадает. Цена, введённая на 1 марта, действует и в сам день 1 марта. Это отличает срез от остатков на дату, где граница по умолчанию не включает момент.

  2. #oc_vt_slices2 / 5
    Как получить последнюю цену товара без виртуальной таблицы среза?
    A)МАКСИМУМ(Период), затем соединение
    B)ПЕРВЫЕ 1 без сортировки по периоду
    C)СУММА(Цена) по товару
    D)Выгрузить регистр и искать в коде
    показать ответ и разбор
    +A)МАКСИМУМ(Период), затем соединение

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

  3. #oc_vt_slices3 / 5
    Курсы валют: условие Источник = &Печать в ГДЕ после СрезПоследних(). Что вернётся для валюты, чей последний курс из интернета?
    A)Ошибка: реквизит в ГДЕ среза недоступен
    B)Последний курс из печатных изданий
    C)Последний курс из интернета
    D)Ничего: строка отброшена
    показать ответ и разбор
    +D)Ничего: строка отброшена

    // разбор: Срез сначала берёт последнюю запись по каждой валюте, и только потом ГДЕ проверяет источник. Если последний курс из интернета, строка отбрасывается целиком. Чтобы получить последний курс именно из печати, условие ставят в параметр среза — пример из методики ИТС.

  4. #oc_vt_slices4 / 5
    Что вернёт запрос для валюты USD, если записи: 19.03 USD 31,00 печать; 20.03 USD 31,10 интернет?
    ВЫБРАТЬ К.Валюта, К.Курс
    ИЗ РегистрСведений.Курсы.СрезПоследних(
      , Источник = &Печать) КАК К
    A)Обе записи USD
    B)USD 31,10
    C)Ничего для USD
    D)USD 31,00
    показать ответ и разбор
    +D)USD 31,00

    // разбор: С условием в параметре срез ищет последнюю запись только среди записей из печатных источников, и для USD это 31,00 от 19 марта. Более поздний интернет-курс в отбор не попал. Это пример из методики ИТС о разнице между отбором в параметре и в ГДЕ.

  5. #oc_vt_slices5 / 5
    Чем срез последних на текущую дату отличается от среза без параметра даты?
    A)Без даты — только записи за сегодня
    B)Без даты — ошибка: период обязателен
    C)На последний момент, будущие тоже
    D)Ничем: подставится текущая дата
    показать ответ и разбор
    +C)На последний момент, будущие тоже

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

дальше

Теорию прочитал. Навык ставится повторением

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