1с запрос остатки на каждый день

Примеры по программированию в 1с 7.7, 8.1, 8.2

понедельник, 9 февраля 2015 г.

1с Запрос 8.2 Остатки на каждый день периода, без движений

Пример запроса 1с 8.2, когда не было движения за период, а необходимо вывести остатки.

Где «ВремТз» — это таблица значений, заполненная датами за месяц:

ВремТз = Новый ТаблицаЗначений;
ВремТз.Колонки.Добавить(«Период»,Новый ОписаниеТипов(«Дата»));

Для сч =0 по Разница Цикл
День_=НачПериода+сч*86400;
ВремТз.Добавить().период = День_;
КонецЦикла;

Вот только запросом:
ВЫБРАТЬ РАЗЛИЧНЫЕ
0 КАК Период
ПОМЕСТИТЬ Дни
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 3
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 4
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 6
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 7
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 8
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 9;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&Началопериода, ДЕНЬ, ДНИ.Период) КАК Период,
Движения.Склад,
СУММА(ВЫБОР
КОГДА Движения.Период = &НачалоПериода
ТОГДА Движения.КоличествоКонечныйОстаток
ИНАЧЕ ВЫБОР
КОГДА Движения.Период

1. Генерация ряда дат.

Большинство генераторов дат запросом, построены на генераторах последовательного ряда чисел выступающих в роли добавляемых дней к начальной дате генерации. Анализ публикаций, по этой теме, на инфостарте показал, что наиболее интересное решение было предложено в публикации «Работаем с датами в запросе», автор даже просит — «Если найдете вариант, который работает быстрее в файловой и в SQL версии 1С:Предприятия 8, то сообщите мне пожалуйста.» Тестирование этого варианта показало, что это действительно наиболее быстрое решение.

Предлагаемый вариант генератора дат построен на публикации «Порождающий запрос» в которой предложен запрос формирующий числа натурального ряда в диапазоне 0 — 1 048 576. Поскольку нам такой большой диапазон не потребуется, то сократим этот запрос на один разряд до диапазона 0-65 536 чисел. Фактически это будет чуть больше 184 лет, что для большинства вариантов использования более чем достаточно.

Как видно из приведенного кода, запрос выглядит более компактно чем в публикации «Работаем с датами в запросе»

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

Запрос генерирует максимально ряд из 256 месяцев

Сравнение быстродействий запросов генераторов дат.

Общие условия тестирования предложенного запроса и запроса «Работаем с датами в запросе»: Платформа — 1С:Предприятие 8.3 (8.3.12.1595), диапазон дат в запросах 01.01.2019-01.01.2185 (60 632 дней).

1. Файловая база данных, 1с сервер, клиент и база на одной ПВМ: вариант Работаем с датами в запросе быстрее предложенного на 20-25%.

2. База данных MS SQL, SQL сервер, 1с сервер и клиент на разных ПВМ: вариант Работаем с датами в запросе медленнее предложенного на 25-30%.

2. Цены на каждый день.

Для построения запроса цен на каждый день был использован запрос получения слеза последних из введения к публикации Заметки по SQL: Срез последних — аналог запроса. Построим по этому принципу запрос среза последних для регистра цен.

Теперь добавим в этот запрос наш генератор ряда дат.

Почему в запросе по ценам нет отбора по периоду регистра сведений?. Потому что роль этого отбора фактически играет запрос генерирующий ряд дат. Условие «РядДат.Дата >= ЦеныНоменклатуры1.Период» выполняет эту функцию, так как даты меньше «&НачалоПериода» не создаются. За счет этого запрос имеет очень хорошую скорость. К сожалению автор не имеет данных, на которых можно было бы протестировать быстродействие этого запроса. Единственное, что могу сказать, что тесты аналогичного запроса проводились на БД Oracle 9i, база не 1с. В качестве сравнения брался запрос построенный на аналитической функции. Скорость предложенного запроса оказалась выше на 20-25%

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

3. Остатки на каждый день.

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

НАЧАЛОПЕРИОДА(ТоварыНаСкладах.Период, ДЕНЬ) КАК Период

Далее, получаем сумму нарастающим итогом — собственно остатки по периоду день.

И наконец, на основе базового запроса публикации Заметки по SQL: Срез последних — аналог запроса, получим данные по остаткам на каждый день. Текст запроса генерирующего ряд дат («РядДат»), можно взять из начала публикации, поэтому здесь я приводить его не буду.

Таким образом используя базовую конструкцию запроса из публикации Заметки по SQL: Срез последних — аналог запроса, имеющую ключевой элемент

МАКСИМУМ([РегистрСведений; РегистрОстатков].Период) = [РегистрСведений; РегистрОстатков].Период

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

Стандартная выборка из виртуального регистра остатков и оборотов не показывает остатки на периодах, в которых нет оборотов. В СКД, то есть вне запроса проблема легко решается, а для использования внутри запроса приходится «городить огород». У многих это выливается в несколько запросов, тогда как можно обойтись и одним. Остатки здесь получаются суммированием оборотов. По тому же принципу платформа рассчитывает остатки внутри периода хранения итогов.
ВЫБРАТЬ РАЗЛИЧНЫЕ
КурсыВалют . Период
ПОМЕСТИТЬ Дни
ИЗ
РегистрСведений . КурсыВалют КАК КурсыВалют
ГДЕ
КурсыВалют . Период МЕЖДУ & НачалоПериода И & КонецПериода
;

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

СГРУППИРОВАТЬ ПО
Движения . Номенклатура ,
ДНИ . Период

Правда, здесь рассчитываются остатки на конец каждого дня (это легко поправить, сдвинув даты на -1). Регистр «КурсыВалют» взят для краткости и для разнообразия — все даты внутри периода можно получать и по другому. Классический вариант проигрывает по быстродействию предложенному примерно в 1.5 раза (проверялось на файловой базе УПП).

Оцените статью
Добавить комментарий