Transformando linhas em colunas no Postgres

 

Esse semana me deparei com um problema no trabalho, onde tive que pegar resultados de linhas de uma tabela e coloca-los como coluna numa junção com outra tabela, como demorei um certo tempo para achar a solução então resolvi publica-la aqui, não sei ao certo se é a solução mais performática ou se é a mais legível, espero os comentários de vocês e caso alguém possua uma artigo mais completo favor postar o link.

No nosso exemplo temos uma empresa M que faz analises de créditos, nessa empresa uma pessoa ao se submeter a análise de crédito será avaliada obrigatoriamente por três tipos de analises: Financeiro, Patrimônio e Pessoal.

Segue abaixo o nosso modelo de entidade relacionamento.

image

Agora o script de criação da estrutura.

CREATE TABLE pessoa
(
  id serial NOT NULL,
  nome character varying(50),
  CONSTRAINT pessoa_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE pessoa
  OWNER TO postgres;

CREATE TABLE tipo_analise_credito
(
  id serial NOT NULL,
  nome character varying(50),
  CONSTRAINT tipo_analise_credito_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tipo_analise_credito
  OWNER TO postgres;


CREATE TABLE analise_credito
(
  id serial NOT NULL,
  id_pessoa integer,
  id_tipo_analise_credito integer,
  aprovado boolean,
  CONSTRAINT analise_credito_pkey PRIMARY KEY (id),
  CONSTRAINT analise_credito_id_pessoa_fkey FOREIGN KEY (id_pessoa)
      REFERENCES pessoa (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT analise_credito_id_tipo_analise_credito_fkey FOREIGN KEY (id_tipo_analise_credito)
      REFERENCES tipo_analise_credito (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE analise_credito
  OWNER TO postgres;

 

Agora vamos popular o banco de dados.

INSERT INTO pessoa(nome) VALUES (‘Daniel’);
INSERT INTO pessoa(nome) VALUES (‘Paulo’);
INSERT INTO pessoa(nome) VALUES (‘João’);

INSERT INTO tipo_analise_credito(nome) VALUES (‘Financeiro’);
INSERT INTO tipo_analise_credito(nome) VALUES (‘Pessoal’);
INSERT INTO tipo_analise_credito(nome) VALUES (‘Patrimonio’);

INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (1, 1, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (1, 2, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (1, 3, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (2, 1, false);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (2, 2, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (2, 3, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (3, 1, true);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (3, 2, false);
INSERT INTO analise_credito(id_pessoa, id_tipo_analise_credito, aprovado) VALUES (3, 3, false);

Pronto já temos estrutura e o banco de dados já está populado, agora segue abaixo o SELECT que é o objetivo desse artigo.

select p.nome,
(select aprovado from analise_credito ac where ac.id_pessoa = p.id and id_tipo_analise_credito = 1) as Financeiro,
(select aprovado from analise_credito ac where ac.id_pessoa = p.id and id_tipo_analise_credito = 2) as Pessoal,
(select aprovado from analise_credito ac where ac.id_pessoa = p.id and id_tipo_analise_credito = 3) as Patrimonio
from pessoa p

A consulta acima é bem simples e resolve o problema quando as linhas são estáticas, no exemplo elas são fixas em 3, essa consulta não funciona quando existir uma variação dinâmica.

Abaixo o resultado da consulta.

image

Espero que de alguma forma eu tenha ajudado vocês!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s