Sentencia SQL recursiva (PostgreSQL 9.1.4)
PostgreSQL 9.1
Situacion de negocios
Cada mes, hay un nuevo lote de cuentas asignadas a un proceso específico. Cada lote se puede describir por mes, número de cuentas y saldo total de cuentas. El objetivo del proceso es recuperar parte del saldo de los clientes. Cada lote se rastrea por separado cada mes (cantidad recuperada en cada mes desde que se transfirió el lote al proceso).
Gol
Mi objetivo es predecir qué cantidad se recuperará en el futuro.
Definicion de datos
create table vintage_data (
granularity date, /* Month when account entered process*/
distance_in_months integer, /* Distance in months from date when accounts entered process*/
entry_accounts integer, /* Number of accounts that entered process in a given month*/
entry_amount numeric, /* Total amount for account that entered process in a given month*/
recovery_amount numeric /* Amount recovered in Nth month on accounts that entered process in a given month */
);
Data de muestra
insert into vintage_data values('2012-01-31',1,200,100000,1000);
insert into vintage_data values('2012-01-31',2,200,100000,2000);
insert into vintage_data values('2012-01-31',3,200,100000,3000);
insert into vintage_data values('2012-01-31',4,200,100000,3500);
insert into vintage_data values('2012-01-31',5,200,100000,3400);
insert into vintage_data values('2012-01-31',6,200,100000,3300);
insert into vintage_data values('2012-02-28',1,250,150000,1200);
insert into vintage_data values('2012-02-28',2,250,150000,1600);
insert into vintage_data values('2012-02-28',3,250,150000,1800);
insert into vintage_data values('2012-02-28',4,250,150000,1200);
insert into vintage_data values('2012-02-28',5,250,150000,1600);
insert into vintage_data values('2012-03-31',1,200,90000,1300);
insert into vintage_data values('2012-03-31',2,200,90000,1200);
insert into vintage_data values('2012-03-31',3,200,90000,1400);
insert into vintage_data values('2012-03-31',4,200,90000,1000);
insert into vintage_data values('2012-04-30',1,300,180000,1600);
insert into vintage_data values('2012-04-30',2,300,180000,1500);
insert into vintage_data values('2012-04-30',3,300,180000,4000);
insert into vintage_data values('2012-05-31',1,400,225000,2200);
insert into vintage_data values('2012-05-31',2,400,225000,6000);
insert into vintage_data values('2012-06-30',1,100,60000,1000);
Proceso de calculo
Puede imaginar los datos como una matriz triangular (los valores de X deben pronosticarse):
distance_in_months 1 2 3 4 5 6
granularity entry_accounts entry_amount
2012-01-31 200 100000 1000 2000 3000 3500 3400 3300
2012-02-28 250 150000 1200 1600 1800 1200 1600 (X-1)
2012-03-31 200 90000 1300 1200 1400 1000 (X0) (X4)
2012-04-30 300 180000 1600 1500 4000 (X1) (X5) (X8)
2012-05-31 400 225000 2200 6000 (X2) (X6) (X9) (X11)
2012-06-30 100 60000 1000 (X3) (X7) (X10) (X12 (X13)
Algoritmo
El objetivo que tengo es pronosticar todos los puntos faltantes (futuro). Para ilustrar el proceso, este es el cálculo para el punto X1.
1) Obtenga los totales de las filas de los tres meses anteriores utilizando una distancia de hasta 4:
2012-01-31 1000+2000+3000+3500=9500 (d4m3)
2012-02-28 1200+1600+1800+1200=5800 (d4m2)
2012-03-31 1300+1200+1400+1000=4900 (d4m1)
2) Obtenga los totales de las filas de los tres meses anteriores utilizando una distancia de hasta 3:
2012-01-31 1000+2000+3000=6000 (d3m3)
2012-02-28 1200+1600+1800=4600 (d3m2)
2012-03-31 1300+1200+1400=3800 (d3m1)
3) Calcule la tasa de ejecución promedio ponderada para la distancia 3 y la distancia 4 (ponderada por entry_amount):
(d4m3+d4m2+d4m1)/(100000+150000+90000) = (9500+5800+4900)/(100000+150000+90000) = 20200/340000 = 0.0594
(d3m3+d3m2+d3m1)/(100000+150000+90000) = (6000+4600+3800)/(100000+150000+90000) = 14400/340000 = 0.0424
4) Calcula el cambio entre la distancia 3 y la distancia 4.
((d4m3+d4m2+d4m1)/(100000+150000+90000))/((d3m3+d3m2+d3m1)/(100000+150000+90000)) =
= (20200/340000)/(14400/340000) =
= 0.0594/0.0424 = 1.403 (PredictionRateForX1)
5) Calcule los totales de fila para el mes predicho usando una distancia de hasta 3:
2012-04-30 1600+1500+4000=7100
6) Calcular la tasa usando entry_amount para el mes predicho
7100/180000 = 0.0394
7) Calcular la tasa prevista para X1
0.0394 * PredictionRateForX1 = 0.05534
8) Calcular la cantidad para X1
(0.05534-0.0394)*180000 = 2869.2
Problema
El problema es cómo calcular el resto de la matriz (de x-1 a x13) mediante la instrucción SQL. Es obvio que esto requerirá algún tipo de algoritmo recursivo.