Представим остатки товара на складе в виде последовательности чисел.
Например, за период с 1 по 5 число остатки товара на складе были равны:
10 10 10 0 5
Данная ситуация сложилась, потому что наш регистр накопления содержал следующие движения:
1 день. +10
4 день. -10
5 день. +5
Для решения задачи в лоб необходимо получить среднее арифметическое конечных остатков товара за каждый день периода. (10 + 10 + 10 + 0 + 5) / 5 = 7
Как сделать то же самое, если имеем только движения регистра за определенные дни (+10,-10,+5)?
Любую последовательность чисел можно разложить на несколько, покомпонентная сумма которых будет равна нашей последовательности.
В виде покомпонентной суммы каких последовательность можно представить нашу последовательность? В виде следующих трёх, каждая из которых состоит из одинаковых чисел.
Обратите внимание, что каждое число последовательностей равно обороту движения регистра за определенный день.
10 10 10 10 10
+ 0 0 0 -10 -10
+ 0 0 0 0 5
------------------------
= 10 10 10 0 5
Найдём среднее арифметическое для каждой из этих трёх последовательностей:
1. (10+10+10+10+10) / 5 = 10 * 5 / 5
2. (0 + 0 + 0 -10- 10) / 5 = -10 * 2 / 5
3. (0 + 0 + 0 +0 +5) / 5 = 5 * 1 / 5
Так как наша первоначальная последовательность получена с помощью покомпонентного сложения этих трёх последовательностей, то среднее арифметическое первоначальной последовательности равно сумме средних арифметических этих трёх последовательностей.
То есть ср.арифметическое μ (10 10 10 0 5) = 10*5/5 - 10*2/5 +5*1/5
Данная формула будет справедлива для любой последовательности n чисел.:
, где
n - количество календарных дней в периоде отчёта (в нашем примере = 5)
k - количество дней, в которых есть движения регистра (в нашем примере = 3)
ak - это значение движения по регистру за определенный день (в нашем примере -- это 10, -10, 5)
bk - номер дня, в котором находится движение регистра (в нашем примере выше -- это дни 1, 4, 5)
Далее тоже самое на языке запросов 1С на примере регистра партий товаров.Но учтём, что конечный остаток первого дня может быть образован не только оборотом первого дня, но и остатком на начало периода, т.е. оборотов за первый день может и не быть, а конечный остаток есть. Поэтому, для первого дня периода надо брать в расчёт уже готовый конечный остаток (ПартииТоваров.КоличествоКонечныйОстаток), ну а для всех следующих дней -- оборот (ПартииТоваров.КоличествоОборот)
// ak = ПартииТоваров.КоличествоОборот
// n-bk = РАЗНОСТЬДАТ(ПартииТоваров.Период, &ДатаКонца, ДЕНЬ)
// n = (РАЗНОСТЬДАТ(&ДатаНачала, &ДатаКонца, ДЕНЬ) + 1)
Запрос. Текст = "ВЫБРАТЬ
|ПартииТоваров.Номенклатура,
|СУММА(ВЫБОР
| КОГДА ПартииТоваров.Период = &ДатаНачала
| ТОГДА ПартииТоваров.КоличествоКонечныйОстаток
| ИНАЧЕ ПартииТоваров.КоличествоОборот
| КОНЕЦ * (РАЗНОСТЬДАТ(ПартииТоваров.Период, &ДатаКонца, ДЕНЬ) + 1))
| / (РАЗНОСТЬДАТ(&ДатаНачала, &ДатаКонца, ДЕНЬ) + 1) КАК СреднийОстаток
|ИЗ РегистрНакопления.ПартииТоваров.ОстаткиИОбороты(&ДатаНач, &ДатаКон,
| День, ДвиженияИГраницыПериода, ) КАК ПартииТоваров
|СГРУППИРОВАТЬ ПО ПартииТоваров.Номенклатура";
//ДатаНач, ДатаКон - даты начала и конца периода отчёта
ДатаНачала = ?(ДатаНач = Дата('00010101000000'), ДатаНач, НачалоДня(ДатаНач))
ДатаКонца = ?(ДатаКон = Дата('00010101000000'), Дата("39991231"), КонецДня(ДатаКон))