segunda-feira, 23 de agosto de 2010

Mais regressões lineares em SQL

Vasculhando o manual do Oracle, encontrei umas funções estatísticas e entre elas algumas funções para calcular regressões lineares. A função REGR_SLOPE() logo revelou-se a mais útil. Ela retorna a inclinação da reta que indica a tendência dos dados.

Para repetir o cálculo do artigo anterior, fiz o seguinte:

select min(idhm)+(2010-min(ano))*regr_slope(idhm, ano)
from indices_municipais
where municipio=130

Tenho a tendência de idhm sobre ano, então adiciono o menor valor de idhm ao produto da tendência pela diferença de anos e obtenho o resultado esperado para 2010 (a base tem dados de 1991 e 2000).

Depois, resolvi classificar os municípios pelo IDHM futuro:

select trunc(min(idhm)+(2010-min(ano))*regr_slope(idhm, ano),3), nome
from indices_municipais natural join municipio
group by nome
order by 1 desc

Essa consulta tem um join com a tabela de municpios, porque eu ainda não decorei todos os códigos. E adicionei um TRUNC(), porque resultados com 18 dígitos cansam os olhos.

A consulta é muito mais simples que a do primeiro artigo, mas será mais rápida? Reescrevi a consulta original para poder classificar todos os municípios.

select trunc(a+2010*b,3), nome from (
select (x2*y-xy*x)/(n*x2-x*x) a, (n*xy-x*y)/(n*x2-x*x) b, nome from (
select count(1) n, sum(ano) x, sum(ano*ano) x2,
sum(idhm) y, sum(idhm*idhm) y2, sum(ano*idhm) xy,
nome
from indices_municipais natural join municipio
group by nome
)
) order by 1 desc

Tabulei os tempos:
Consulta com REGR_SLOPEConsulta complicada
0,015s0,014s
0,015s0,014s
0,016s0,013s
0,014s0,017s
0,021s0,015s
0,013s0,014s
0,016s0,015s
0,023s0,015s
0,015s0,021s
0,015s0,014s

Então, a consulta complicada foi mais rápida em 8 das 10 execuções. Ambas produzem 467 linhas (o município campeão é Ibiaçá).

Nenhum comentário: