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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

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

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

Способ 1. Использование расширения языка запросов СКД и отключение автозаполнения

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

Разберем по шагам, как правильно оформить запрос во втором наборе данных:

  1. Откроем набор данных — запрос, в котором выбираются курсы валют.
  2. В тексте запроса укажем параметр периода виртуальной таблицы в фигурных скобках: {(&Дата)}.
  3. На вкладке Наборы данных выключим флаг Автозаполнение для второго набора или вручную переопределим заполнение полей.

Посмотрим на пример текста запроса для второго набора данных с использованием расширения языка СКД:


ВЫБРАТЬ
    &Дата КАК Дата,
    КурсыВалютСрезПоследних.Валюта КАК Валюта,
    КурсыВалютСрезПоследних.Курс КАК Курс,
    КурсыВалютСрезПоследних.Кратность КАК Кратность
{ВЫБРАТЬ
    Дата,
    Валюта.*,
    Курс,
    Кратность}
ИЗ
    РегистрСведений.КурсыВалют.СрезПоследних({(&Дата)}, Валюта = &Валюта) КАК КурсыВалютСрезПоследних
{ГДЕ
    КурсыВалютСрезПоследних.Курс,
    КурсыВалютСрезПоследних.Кратность}

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

Также проверим настройки на вкладке Связи наборов данных:

  1. В качестве источника указываем первый набор данных, в качестве приемника — второй набор.
  2. В поле Выражение источник передаем поле даты (например, Дата или ДокументОприходования.Дата).
  3. В поле Выражение приемник указываем поле приемника.
  4. В колонке Параметр обязательно указываем имя параметра: Дата (а для валюты — отдельной строкой параметр Валюта).

Способ 2. Объединение данных в один набор с помощью пакетного запроса

Связь наборов данных через параметры в СКД выполняет запрос второго набора итеративно (отдельным запросом на каждую уникальную строку первого набора). На больших объемах документов это может приводить к снижению производительности.

Более эффективным решением является отказ от двух наборов данных в пользу одного набора данных с пакетным запросом.

Рассмотрим алгоритм получения среза последних на каждую дату в рамках одного запроса:

  1. В первом запросе пакета поместим во временную таблицу список документов с их датами и валютами.
  2. Во втором запросе соединим временную таблицу с реальной таблицей регистра РегистрСведений.КурсыВалют по условию Период <= ВТ.Дата и сгруппируем по документу, выбрав МАКСИМУМ(Период).
  3. В третьем запросе пакета соединим полученные срезные даты с таблицей регистра курсов для получения актуальных значений ресурсов (курса и кратности).

Проанализируем пример такого пакетного запроса:


ВЫБРАТЬ
    Партии.ДокументОприходования КАК Документ,
    Партии.ДокументОприходования.Дата КАК Дата,
    Партии.ДокументОприходования.Валюта КАК Валюта
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    РегистрНакопления.ТоварыВРознице КАК Партии;

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Документ КАК Документ,
    ВТ.Дата КАК Дата,
    ВТ.Валюта КАК Валюта,
    ЕСТЬNULL(Курсы.Курс, 1) КАК Курс,
    ЕСТЬNULL(Курсы.Кратность, 1) КАК Кратность
ИЗ
    ВТ_Документы КАК ВТ
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_МаксДаты КАК МаксДаты
        ПО МаксДаты.Документ = ВТ.Документ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Курсы
        ПО Курсы.Валюта = МаксДаты.Валюта
        И Курсы.Период = МаксДаты.Период

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

← На главную