У меня есть следующий запрос, чтобы получить среднее значение единиц за предыдущие 12 месяцев в интервале, но моя проблема в том, что 12 предыдущих месяцев не учитывают первую неделю ISO в году, скажем, этот пример:
SELECT
*,
avg(units) OVER (
ORDER BY to_date(year::text || '-' || week::text, 'IYYY-IW')
RANGE between interval '12 months' preceding and current row)
FROM
rolling_year_table
order by year,week;
В основном 1-я неделя ISO 2020 года (фактически «2019-12-30» не учитывается в расчетах.
Есть ли способ указать 12 месяцев предыдущей и текущей строки, но с использованием недель ISO?
Спасибо,
Разве это не делает то, что вы хотите?
select ry.*,
avg(units) over (
order by year * 100 + week
range between 100 preceding and current row
from rolling_year_table
order by year,week;
Предположим, что текущая строка — это 2020 год и 45-я неделя, это приведет к тому, что строки с той же недели в 2019 году будут перенесены в текущую строку.
Это слишком долго для комментария.
Я не думаю, что есть простой способ сделать это. Проблема в несоответствии "неделя" и "год". В 12-месячном периоде около 52,2 недели. Итак, вы спрашиваете, что иногда период «12 месяцев» имеет 52 недели, а иногда 53 недели.
Я думаю, вы могли бы сделать кумулятивный расчет на основе последних 52 недель, а затем использовать логику условий, чтобы включить предыдущую 53-ю неделю. Проблема в . . . Я не знаю, каковы точные правила возврата на 53 недели назад.
Если единственная проблема заключается в том, что в 53-ю неделю года следует включить весь год, то это будет довольно легко включить. Псевдокод для этого будет:
(case when isoweek = 53
then avg() over (. . . range between '53 week' preceding and current row)
else avg() over (. . . range between '52 week' preceding and current row)
end)
Обновлено:
Я не уверен на 100%, сработает ли это для вашего варианта использования. Но у меня есть идея, которая может сделать то, что вы хотите. То есть перечислить недели года как части года. Таким образом, годы с 52 неделями будут иметь одно исчисление, а годы с 53 неделями — другое.
Это будет выглядеть так:
select . . .,
avg(units) over (order by year + (isoweek - 1) / weeks_in_year
range between 1 preceding and current row
)
from (select t.*,
extract(isoyear from dte) as isoyear,
extract(week from dte) as isoweek,
greatest(extract(week from date_trunc('year', dte) + interval '1 year - 1 day'), 53) as weeks_in_year
f from t
) t;
Вам нужно будет проверить это, чтобы увидеть, делает ли он то, что вы действительно хотите. Как я сказал в начале этого ответа, «12 месяцев назад» не имеет четкого определения для недель ISO, но это может быть разумной интерпретацией.
@Матиас. . . Я не полностью понимаю ваш комментарий. Изогод не принимается во внимание при возврате назад на 52 или 53 недели.
Спасибо, единственная проблема, с которой я столкнулся, заключается в том, что возврат на 52 или 53 недели назад не соответствует, например, неделе 1 в 2020 году, поскольку он показан как декабрь 2019 года.