postgres postgresql math average postgresql-9.1 moving-average

postgresql - get median postgres



Promedio móvil en postgresql (2)

Creo que una mejor respuesta podría ser:

SELECT date, shop_id, amount, extract(dow from date) AS dow, CASE WHEN count(amount) OVER w = 3 THEN avg(amount) OVER w END AS average_amt FROM ro WHERE extract(dow from date) = 4 WINDOW w AS (ORDER BY date DESC ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING)

Creo que es más limpio usar la misma ventana tanto para verificar el número de filas en la ventana como para tomar el promedio. (Esto también guarda dos agregaciones de ventanas, como se puede ver en la respuesta original).

Con respecto a la afirmación en la respuesta anterior de que "mi consulta evita la computación innecesaria al filtrar los jueves antes de aplicar las costosas funciones de la ventana", esto también se aplica a la consulta sugerida por el OP y a mi consulta, como anexo EXPLAIN a cualquiera de los programas.

Tengo la siguiente tabla en mi base de datos Postgresql 9.1:

select * from ro; date | shop_id | amount -----------+----------+-------- 2013-02-07 | 1001 | 3 2013-01-31 | 1001 | 2 2013-01-24 | 1001 | 1 2013-01-17 | 1001 | 5 2013-02-10 | 1001 | 10 2013-02-03 | 1001 | 4 2012-12-27 | 1001 | 6 2012-12-20 | 1001 | 8 2012-12-13 | 1001 | 4 2012-12-06 | 1001 | 3 2012-10-29 | 1001 | 3

Estoy tratando de obtener un promedio móvil comparando los datos con los últimos 3 jueves, sin incluir el jueves actual. Aquí está mi consulta:

select date, shop_id, amount, extract(dow from date), avg(amount) OVER (PARTITION BY extract(dow from date) ORDER BY date DESC ROWS BETWEEN 0 PRECEDING AND 2 FOLLOWING) from ro where extract(dow from date) = 4

Este es el resultado dado.

date | shop_id | amount | date_part | avg -----------+----------+--------+-----------+-------------------- 2013-02-07 | 1001 | 3 | 4 | 2.0000000000000000 2013-01-31 | 1001 | 2 | 4 | 2.6666666666666667 2013-01-24 | 1001 | 1 | 4 | 4.0000000000000000 2013-01-17 | 1001 | 5 | 4 | 6.3333333333333333 2012-12-27 | 1001 | 6 | 4 | 6.0000000000000000 2012-12-20 | 1001 | 8 | 4 | 5.0000000000000000 2012-12-13 | 1001 | 4 | 4 | 3.5000000000000000 2012-12-06 | 1001 | 3 | 4 | 3.0000000000000000

Espero

date | shop_id | amount | date_part | avg -----------+----------+--------+-----------+-------------------- 2013-02-07 | 1001 | 3 | 4 | 2.6666666666666667 2013-01-31 | 1001 | 2 | 4 | 4.0000000000000000 2013-01-24 | 1001 | 1 | 4 | 6.3333333333333333 2013-01-17 | 1001 | 5 | 4 | 6.0000000000000000 2012-12-27 | 1001 | 6 | 4 | 5.0000000000000000 2012-12-20 | 1001 | 8 | 4 | 2012-12-13 | 1001 | 4 | 4 | 2012-12-06 | 1001 | 3 | 4 |


SQL Fiddle

select "date", shop_id, amount, extract(dow from date), case when row_number() over (order by date) > 3 then avg(amount) OVER ( ORDER BY date DESC ROWS BETWEEN 1 following AND 3 FOLLOWING ) else null end from ( select * from ro where extract(dow from date) = 4 ) s

Lo que está mal con la consulta del OP es la especificación del marco:

ROWS BETWEEN 0 PRECEDING AND 2 FOLLOWING

Aparte de eso, mi consulta evita la computación innecesaria al filtrar los jueves antes de aplicar las costosas funciones de la ventana.

Si es necesario particionar por shop_id, obviamente agregue la partition by shop_id a ambas funciones, avg y row_number .