¿Cómo puedo agrupar los datos por días que han pasado y que se han acumulado en PostgreSQL? (<30, 31-60, 61-90, 91+)

Soy nuevo en PostgreSQL y escribo enunciados SQL en general, ¡así que estoy buscando un poco de ayuda!

Todos mis datos están en una sola tabla (counts), y necesito ingresar un valor en dólares (recovery_amount), dos dates (appeal_date y recovery_date), y finalmente agrupar los datos por la diferencia de appeal_date y recovery_date para ver el total recovery_amount a medida que los días maduran.

Algo así como (date_de_depósito – date de apelación) en días = total_de_restacción_restaurante en <30 días, total_de_restauración total en 31-60 días, total de cantidad_de recuperación en 61-90 días y total_de_restauración en 90 días.

Estoy intentando declaraciones como:

SELECT recovery_amount AS "Total" CASE when (appeal_date - payment_date) >= 90 then 90 when (appeal_date - payment_date) >= 60 then 60 when (appeal_date - payment_date) >= 30 then 30 else 0 END GROUP FROM accounts GROUP BY "Total" 

El objective final es usar esta información en un gráfico de barras (si eso te ayuda a visualizar el razonamiento).

Esto está obviamente fuera de lugar, ya que he estado probando muchas variaciones en vano.

¡Cualquier ayuda que ustedes / chicas puedan dar es muy apreciada! ¡Gracias por adelantado!

No tan lejos…

 SELECT sum(recoveryTotal) as TotalAmount, --if you want the overall total sum (case when (appeal_date - payment_date) >= 90 then recoveryTotal else 0 end) as total90, sum (case when (appeal_date - payment_date) >= 60 then recoveryTotal else 0 end)as total60, sum (case when (appeal_date - payment_date) >= 30 then recoveryTotyl else 0 end) as total30 FROM accounts 

Si desea mantener los datos en 3 columnas.

 SELECT count(*) NoOfAccts, sum(recovery_amount) AS "GroupTotal" CASE when (appeal_date - payment_date) >= 90 then 90 when (appeal_date - payment_date) >= 60 then 60 when (appeal_date - payment_date) >= 30 then 30 else 0 END GROUP FROM accounts GROUP BY CASE when (appeal_date - payment_date) >= 90 then 90 when (appeal_date - payment_date) >= 60 then 60 when (appeal_date - payment_date) >= 30 then 30 else 0 END 

Daría lugar a algo así como

 NoOfAccts GroupTotal Group 22 3754.48 90 96 24834.83 60 123 38348.48 30 9999 1824389.83 0 

Una solución a esto es la agregación condicional (ver la respuesta de Raphaël).

Si realmente no necesita esto como columnas separadas, puede hacerlo un poco más dynamic (= más fácil de mantener) si usa una list de ranges. Como está planeando usar eso para un informe, eso debería estar bien

 with limits (range) as ( values (int4range(0,30,'[)')), (int4range(30,60,'[)')), (int4range(60,90,'[)')), (int4range(90,null,'[)')) ) select l.range as day_range, sum(coalesce(recovery_amount,0)) as total from limits l left join accounts ac on (ac.appeal_date - ac.payment_date) <@ l.range group by range order by range; 

Ejemplo: http://rextester.com/UYDOV15732

Ahora, si quiere un nuevo range, simplemente agregue eso a la list de ranges sin cambiar la consulta real. Incluso podría generar automáticamente ranges del mismo tamaño a partir de los datos que se ajustan automáticamente a los datos en la tabla.

Debería poder usar DATE_PART para encontrar la diferencia en días, http://www.sqlines.com/postgresql/how-to/datediff .

Entonces, si estoy entendiendo correctamente que está tratando de agrupar el monto de la recuperación total por la diferencia de date, algo como:

  SELECT CASE DATE_PART('day', appeal_date - payment_date) WHEN <= 30 THEN '<=30' WHEN BETWEEN 31 and 60 THEN '31-60' WHEN BETWEEN 61 and 90 THEN '61-90' WHEN > 90 THEN '>90' ELSE 0 END as 'DateRange', SUM(recovery_amount) AS "Total" FROM accounts GROUP BY CASE DATE_PART('day', appeal_date - payment_date) WHEN <= 30 THEN '<=30' WHEN BETWEEN 31 and 60 THEN '31-60' WHEN BETWEEN 61 and 90 THEN '61-90' WHEN > 90 THEN '>90' ELSE 0 END