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 |
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
.