<< Click to Display Table of Contents >>

Resumo do que se trata

Inverter linhas e colunas

Como funciona

Existe uma function feita em C dentro do próprio PG, basta declará-la 1 vez por base.

Declarando a função

create or replace function crosstab(text)

returns setof record

as '$libdir/tablefunc','crosstab'

language C stable strict;

 

A tal libdir fica em 

C:\Arquivos de programas\PostgreSQL\8.3\share\contrib

Ali tem várias funções bem legais... porém não tive tempo de ver ainda.

Vamos testar

Primeira passo criamos uma tabela (simples para este exemplo) onde vamos cadastrar alguns carros com suas marcas e modelos:

create table tabela(id serial, marca text, modelo text);

 

Inserir os dados para teste:

insert into tabela(marca, modelo, ano) values('ford'     ,'ka'    );

insert into tabela(marca, modelo, ano) values('wv'       ,'fusca' );

insert into tabela(marca, modelo, ano) values('chevrolet','celta' );

insert into tabela(marca, modelo, ano) values('renault'  ,'clio'  );

insert into tabela(marca, modelo, ano) values('renault'  ,'megane');

insert into tabela(marca, modelo, ano) values('ford'     ,'taurus');

insert into tabela(marca, modelo, ano) values('wv'       ,'fox'   );

insert into tabela(marca, modelo, ano) values('wv'       ,'passat');

insert into tabela(marca, modelo, ano) values('chevrolet','vectra');

insert into tabela(marca, modelo, ano) values('ford'     ,'focus' );

insert into tabela(marca, modelo, ano) values('ford'     ,'fiesta');

 

Se quisermos ver todos os da marca ford:

select modelo from tabela where marca = 'ford'

 

 id | marca | modelo

----+-------+--------

  1 | ford  | ka

  6 | ford  | taurus

 10 | ford  | focus

 11 | ford  | fiesta

(4 rows)

 

Bom, até aqui tudo bem, mas e se eu quisesse um resultado invertido linhas e colunas, tipo: uma linha para cada marca e cada modelo sendo uma coluna, loucura né? Será que é possível, claro que sim! senão eu não teria perdido tempo em fazer esse help!

Como funciona a mágica

select * from 

  crosstab('select marca as identificador, marca, modelo from tabela order by marca, modelo;') as 

           tabela(marca text, modelo1 text, modelo2 text, modelo3 text, modelo4 text);

 

resultado:

   marca   | modelo1 | modelo2 | modelo3 | modelo4

-----------+---------+---------+---------+---------

 chevrolet | celta   | vectra  |         |

 ford      | fiesta  | focus   | ka      | taurus

 renault   | clio    | megane  |         |

 wv        | fox     | fusca   | passat  |

(4 rows)

 

Baba nego, baba.

A explicação: o primeiro campo do select passado como parâmetro para o crosstab indica para o crosstab qual campo deve ser observado para que, enquanto o resultado não mudar ele irá retornar o último campo (sempre tem que ser 3) na mesma linha. O segundo campo (marca) fica como primeira coluna no resultset. Note que as colunas de saída devem ser especificadas com seus tipos, sendo que com exceção da primeira, as demais devem ser colocadas manualmente (conforme a necessidade)

No help do próprio PG tem mais informações

http://www.postgresql.org/docs/8.3/static/tablefunc.html