Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

LUIZHVAISCONCELOS

em SELECT e JOIN

Recommended Posts

Olá pessoal,

venho por meio deste tentar solucionar um problema que estamos passando aqui no trabalho no Ministério da Saúde.

Nós temos um programa de atendimento em PHp e Postgres e há um relatorio onde pode gerar o nome da pessoa=Luiz,Tipo= Comercial ou celular, Numero telefonico=2222-2222, Ramal=7777, Email=luizhvaisconcelos@xxxxx.com.br.

O problema todo é que se o usuário tiver varios telefones ou email ou ambos ele sempre repete o nome do usuario. O select está sendo feito assim;

SELECT A.CO_SEQ_ACESSO, A.NO_PESSOA,

CASE

WHEN B.CO_TIPO_TELEFONE = 1

THEN 'COMERCIAL'

WHEN B.CO_TIPO_TELEFONE = 3

THEN 'CELULAR'

END,

B.NU_DDD, B.NU_TELEFONE, B.NU_RAMAL, C.DS_EMAIL

FROM DBATENDIMENTO.TB_PESSOA_ACESSO A

LEFT JOIN DBATENDIMENTO.TB_TELEFONE B ON A.CO_SEQ_ACESSO = B.CO_PESSOA_ACESSO

LEFT JOIN DBATENDIMENTO.RL_EMAIL C ON A.CO_SEQ_ACESSO = C.CO_PESSOA_ACESSO

 

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Imagem Postada

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 

A imagem à cima exibe exatamente como é impresso na tela no relatorio em php, note que eu que tenho dois email cadastrado ele repete 2 vezes cada um e enquanto o Alexandre que tem só ele exibe apenas o unico cadastrado.

Há alguma possibilidade de fazer esse JOIN ou algo parecido?

 

Muito obrigado pela atenção!

 

Atenciosamente

Luiz

Compartilhar este post


Link para o post
Compartilhar em outros sites

A imagem aqui não abriu, mas pelo que entedi o seu problema é que você tem várias linhas com informações repetidas, apenas mudando alguns valores de uma para outra, correto?

 

O que você pode fazer é usar uma função de agregação que irá juntar todos os resultados de uma coluna em uma única linha. Particulamente, eu uso o array_accum (http://www.postgresql.org/docs/8.2/static/xaggr.html), onde ele coloca cada valor como se fosse um elemento de um array, retornando apenas uma linha.

 

Com isso, você só precisa na camada de cima pegar o array e percorrê-lo.

 

Então, teoricamente (já que não tenho como testar :P), você pode fazer:

 

SELECT A.CO_SEQ_ACESSO, 
		A.NO_PESSOA, 
		(SELECT array_accum(B.CO_TIPO_TELEFONE || ':' || B.NU_DDD || ':' || B.NU_TELEFONE || ':' || B.NU_RAMAL)
				FROM DBATENDIMENTO.TB_TELEFONE 
				WHERE A.CO_SEQ_ACESSO = B.CO_PESSOA_ACESSO
		) as telefones,
		(SELECT array_accum(C.DS_EMAIL) 
				FROM DBATENDIMENTO.RL_EMAIL C 
				WHERE A.CO_SEQ_ACESSO = C.CO_PESSOA_ACESSO
		) as emails
		FROM DBATENDIMENTO.TB_PESSOA_ACESSO A

 

Nesse caso, eu fiz com sub-selects, apenas para ficar de fácil entedimento. Note que no telefone eu mando um array cujos elementos internos são separados por : . Assim, você vai receber apenas uma linha por pessoa e, no campo telefones, um array de n telefones cujos elementos são separados por :, bastando você no php dar o explode por :

 

 

Ainda, é possível fazer o código acima sem uso de subselects, com os left joins que você utilizou. Para isso, no final, você precisará projetar os campos que não são agregados com o group by.

 

Também, acredito que você usar o CASE WHEN com concatenação de campos (CASE WHEN ... THEN ... END || '') não funcionaria... você teria que fazer CASE WHEN ... THEN ... || '' END, fazendo a concatenação dos campos dentro do THEN

 

Bom, acho que é isso :P Se eu tiver errado em alguma parte, avisa ae, já que fiz meio de cabeça ^^

Compartilhar este post


Link para o post
Compartilhar em outros sites

A imagem aqui não abriu, mas pelo que entedi o seu problema é que você tem várias linhas com informações repetidas, apenas mudando alguns valores de uma para outra, correto?

 

O que você pode fazer é usar uma função de agregação que irá juntar todos os resultados de uma coluna em uma única linha. Particulamente, eu uso o array_accum (http://www.postgresql.org/docs/8.2/static/xaggr.html), onde ele coloca cada valor como se fosse um elemento de um array, retornando apenas uma linha.

 

Com isso, você só precisa na camada de cima pegar o array e percorrê-lo.

 

Então, teoricamente (já que não tenho como testar :P), você pode fazer:

 

SELECT A.CO_SEQ_ACESSO, 
		A.NO_PESSOA, 
		(SELECT array_accum(B.CO_TIPO_TELEFONE || ':' || B.NU_DDD || ':' || B.NU_TELEFONE || ':' || B.NU_RAMAL)
				FROM DBATENDIMENTO.TB_TELEFONE 
				WHERE A.CO_SEQ_ACESSO = B.CO_PESSOA_ACESSO
		) as telefones,
		(SELECT array_accum(C.DS_EMAIL) 
				FROM DBATENDIMENTO.RL_EMAIL C 
				WHERE A.CO_SEQ_ACESSO = C.CO_PESSOA_ACESSO
		) as emails
		FROM DBATENDIMENTO.TB_PESSOA_ACESSO A

 

Nesse caso, eu fiz com sub-selects, apenas para ficar de fácil entedimento. Note que no telefone eu mando um array cujos elementos internos são separados por : . Assim, você vai receber apenas uma linha por pessoa e, no campo telefones, um array de n telefones cujos elementos são separados por :, bastando você no php dar o explode por :

 

 

Ainda, é possível fazer o código acima sem uso de subselects, com os left joins que você utilizou. Para isso, no final, você precisará projetar os campos que não são agregados com o group by.

 

Também, acredito que você usar o CASE WHEN com concatenação de campos (CASE WHEN ... THEN ... END || '') não funcionaria... você teria que fazer CASE WHEN ... THEN ... || '' END, fazendo a concatenação dos campos dentro do THEN

 

Bom, acho que é isso :P Se eu tiver errado em alguma parte, avisa ae, já que fiz meio de cabeça ^^

 

Danilo Passos MUITO OBRIGADO!

 

Nós fizemos umas mudanças para poder rodar, olha só:

 

 

SELECT A.CO_SEQ_ACESSO,

A.NO_PESSOA, telefones.TELEFONE, emails.EMAIL

FROM DBATENDIMENTO.TB_PESSOA_ACESSO A

LEFT OUTER JOIN (SELECT B.CO_PESSOA_ACESSO, array_accum(D.ds_tipo_telefone || ':' || B.NU_DDD || ':' || B.NU_TELEFONE || ':' || CASE WHEN B.NU_RAMAL IS NOT NULL THEN B.NU_RAMAL ELSE 0 END) as TELEFONE

FROM DBATENDIMENTO.TB_TELEFONE B, DBATENDIMENTO.TB_TIPO_TELEFONE D

WHERE B.CO_TIPO_TELEFONE = D.CO_TIPO_TELEFONE

GROUP BY B.CO_PESSOA_ACESSO) as telefones ON A.CO_SEQ_ACESSO = telefones.CO_PESSOA_ACESSO

LEFT OUTER JOIN (SELECT C.CO_PESSOA_ACESSO, array_accum('''' ||C.DS_EMAIL || '''') AS EMAIL

FROM DBATENDIMENTO.RL_EMAIL C

GROUP BY C.CO_PESSOA_ACESSO

) as emails ON A.CO_SEQ_ACESSO = emails.CO_PESSOA_ACESSO

 

Mas cara foi um Start muito bom pra gente, novamente muito obrigado!

Abs

Compartilhar este post


Link para o post
Compartilhar em outros sites

De nada, Luiz >) Bom que eu pude ajudar :)

 

Tem várias funções de agregação, e você mesmo pode fazer as suas se necessário ^^ Qualquer coisa, estamos ae para ajudar.

 

Abraços

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.