Этот очень простой SQL может вычислять средние, медианы и т. Д. Для четко определенных периодов, таких как год, месяц, квартал, неделя, день:
SELECT
date_trunc('year', t.time2), -- or hour, day, week, month, year
count(1),
percentile_cont(0.25) within group (order by t.price) as Q1,
percentile_cont(0.5) within group (order by t.price) as Q2,
percentile_cont(0.75) within group (order by t.price) as Q3,
avg(t.price) as A,
min(t.price) as Mi,
max(t.price) as Mx
FROM my_table AS t
GROUP BY 1
ORDER BY date_trunc
Таблица содержит список отдельных транзакций с датой (отметка времени) и цена (bigint).
Однако я изо всех сил пытаюсь адаптировать ее для расчета текущих / движущихся значений (например, 4 недели, или 6 месяцев, или 2 квартала, или 12 месяцев). Как этого достичь?
РЕДАКТИРОВАТЬ Вот как выглядят данные:
И это ожидаемый результат:
РЕДАКТИРОВАТЬ 2:
Другая проблема, с которой я сталкиваюсь, заключается в том, что должен быть полный набор данных, включенных в перемещение avg, median и т. Д. расчеты.
Я имею в виду, что если ряд данных начинается в январе 2000 года, то первые «12-месячные скользящие средние», которые имеют смысл, могут быть рассчитаны только в декабре 2000 года (т. Е. Первый месяц, который содержит полные 12 месяцев). данных). В случае 3-месячного смещения avg, первое значимое значение будет в марте 2000 года и т. Д.
Итак, я думаю, что логика для этого запроса должна быть:
1) определить дату начала и окончания для использования при вычислении avg, медианы и т. д., затем
2) цикл по вычислениям avg, median и т. д. ДЛЯ КАЖДОЙ пары начальных и конечных дат.
Для иллюстрации, первая часть может быть:
WITH range_values AS ( -- get min and max values for the data series
SELECT date_trunc('month', min(time2)) as minval,
date_trunc('month', max(time2)) as maxval
FROM my_table),
period_range(d) AS ( -- generate complete list of periods eg. weeks, months, years for the data series
SELECT generate_series(minval, maxval, '1 month'::interval) as timeint
FROM range_values
),
lookup_range AS ( -- generate start-end date pairs based on the data series
select d as enddate, d- interval '11month' as startdate
from period_range
)
SELECT startdate, enddate
from lookup_range, range_values as p
where enddate >= p.minval + interval '11month'; -- clip date range to calculate 12 months avg using 12 months of data only
Вторая часть может быть (не правильный запрос, а просто для иллюстрации логики):
SELECT
count(1),
percentile_cont(0.5) within group (order by t.price) as median_price,
avg(t.price) as avg_price
FROM my_table as t, lookup_range as l
WHERE t.time2>= 'startdate' AND t.time2 < 'enddate'
Теперь задача состоит в том, какобъединить два? И как заставить его работать с минимальными строками кода?