.comment-link {margin-left:.6em;}

Tuesday, January 10, 2006

PIVOT

Uma técnica comum em SQL é o Pivot. Algumas vezes temos necessidade de apresentar relatórios por grupo, por exemplo o cliente possui alguns telefones de contato, mas eles estão em registros diferentes ao longo da tabela, por que no desenho, cada registro do telefone mostra se o número é residência, celular ou comercial (tipo 1, 2 ou 3).

Exemplo!

Primeiro os dados - T é a tabela onde estão os telefones, nm_tel número e tipo_fone classificação em residência, celular ou comercial.

SQL> select * from t;

COD_CLIENTE NM_TEL TIPO_FONE
------------- ------------- -------------
5 50832590 1
5 55727019 2
6 62856486 1
6 97465225 2
6 36676744 2
7 65214314 1
7 99042269 1
8 69528914 3
8 91252514 1

9 rows selected.

Como podemos notar, temos 4 clientes diferentes e, em nosso exemplo o número de telefones diferentes por cliente é razoável para fazermos um pivot em sql puro, em outra oportunidade, mostrarei um pivot genérico usando pl/sql.

De volta ao exemplo, para saber quantas colunas devemos distribuir os números de telefone por cliente, pegamos o maior valor da quantidade de telefones por cliente.

SQL>
SQL> select max(cnt)
2 from ( select cod_cliente, count(*) cnt
3 from t
4 group by cod_cliente )
5 /

MAX(CNT)
-------------
3

1 row selected.

3 (três), portanto. Com essa informação, montamos nosso pivot para apresentar o cliente e seus respectivos telefones - tudo em uma linho só. O uso do max() é um truque para que seu result set não vire uma "escada" (para ver o efeito escada, basta retirar o max da query).

SQL>
SQL> select cod_cliente,
2 max(decode(rn, 1, nm_tel, null)) nm_tel1,
3 max(decode(rn, 2, nm_tel, null)) nm_tel2,
4 max(decode(rn, 3, nm_tel, null)) nm_tel3
5 from (
6 select cod_cliente, nm_tel,
7 row_number() over (partition by cod_cliente
8 order by cod_cliente ) rn
9 from t
10 )
11 group by cod_cliente
12 /

COD_CLIENTE NM_TEL1 NM_TEL2 NM_TEL3
------------- ------------- ------------- -------------
5 55727019 50832590
6 97465225 62856486 36676744
7 65214314 99042269
8 69528914 91252514

4 rows selected.

Labels:


Comments:
Qual seria a solução usada/pensada para caso não se conheça antecipadamente o número de Telefones?
 
Vou escrever um artigo exclusivp para tratar disso, basicamente seria um função em pl/sql que receberá como argumento a query e devolverá um refcursor com as colunas.
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?