Problema com Join em tabelas

PostgreSQL

20/05/2019

Vou postar meu atual código, e depois vou explicar meu problema:

SELECT
at_atendimento.Atendimento AS at_atendimento_Atendimento,
at_atendimento.Data AS at_atendimento_Data,
at_atendimento.fechado AS at_atendimento_fechado,
at_atendimento.transmitido AS at_atendimento_transmitido,
at_atendimento.Id AS at_atendimento_Id,
at_atendimento_cad_cliente_cartao_cad_cliente.Documento AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento,
at_atendimento_cad_cliente_cartao_cad_cliente.Documento2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento2,
at_atendimento_cad_cliente_cartao_cad_cliente.RazaoSocial AS at_atendimento_cad_cliente_cartao_cad_cliente_RazaoSocial,
at_atendimento_cad_cliente_cartao_cad_cliente.NomeFantasia AS at_atendimento_cad_cliente_cartao_cad_cliente_NomeFantasia,
at_atendimento_cad_cliente_cartao_cad_cliente.Cep AS at_atendimento_cad_cliente_cartao_cad_cliente_Cep,
at_atendimento_cad_cliente_cartao_cad_cliente.Endereco AS at_atendimento_cad_cliente_cartao_cad_cliente_Endereco,
at_atendimento_cad_cliente_cartao_cad_cliente.Numero AS at_atendimento_cad_cliente_cartao_cad_cliente_Numero,
at_atendimento_cad_cliente_cartao_cad_cliente.Complemento AS at_atendimento_cad_cliente_cartao_cad_cliente_Complemento,
at_atendimento_cad_cliente_cartao_cad_cliente.Bairro AS at_atendimento_cad_cliente_cartao_cad_cliente_Bairro,
at_atendimento_cad_cliente_cartao_cad_cliente.Cidade AS at_atendimento_cad_cliente_cartao_cad_cliente_Cidade,
at_atendimento_cad_cliente_cartao_cad_cliente.Estado AS at_atendimento_cad_cliente_cartao_cad_cliente_Estado,
at_atendimento_cad_cliente_cartao_cad_cliente.RamoPrincipal AS at_atendimento_cad_cliente_cartao_cad_cliente_RamoPrincipal,
at_atendimento_cad_cliente_cartao_cad_cliente.Tel1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel1,
at_atendimento_cad_cliente_cartao_cad_cliente.Ramal1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal1,
at_atendimento_cad_cliente_cartao_cad_cliente.Tel2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel2,
at_atendimento_cad_cliente_cartao_cad_cliente.Ramal2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal2,
at_atendimento_cad_cliente_cartao_cad_cliente.IsEmiteBoleto AS at_atendimento_cad_cliente_cartao_cad_cliente_IsEmiteBoleto,
at_atendimento_cad_cliente_cartao_cad_cliente.TipoDocumento AS at_atendimento_cad_cliente_cartao_cad_cliente_TipoDocumento,
at_atendimento_cad_cliente_cartao_cad_cliente.AutorizacaoLancamento AS at_atendimento_cad_cliente_cartao_cad_cliente_AutorizacaoLancamento,
at_atendimento_cad_cliente_cartao_cad_cliente.Id AS at_atendimento_cad_cliente_cartao_cad_cliente_Id,
at_atendimento_cad_cliente_cartao.Cartao AS at_atendimento_cad_cliente_cartao_Cartao,
at_atendimento_cad_cliente_cartao.CodigoAdministrativo AS at_atendimento_cad_cliente_cartao_CodigoAdministrativo,
at_atendimento_cad_cliente_cartao.Contrato AS at_atendimento_cad_cliente_cartao_Contrato,
at_atendimento_cad_cliente_cartao.Validade AS at_atendimento_cad_cliente_cartao_Validade,
at_atendimento_cad_cliente_cartao.SigepUser AS at_atendimento_cad_cliente_cartao_SigepUser,
at_atendimento_cad_cliente_cartao.SigepSenha AS at_atendimento_cad_cliente_cartao_SigepSenha,
at_atendimento_cad_cliente_cartao.Descricao AS at_atendimento_cad_cliente_cartao_Descricao,
at_atendimento_cad_cliente_cartao.desativado AS at_atendimento_cad_cliente_cartao_desativado,
at_atendimento_cad_cliente_cartao.Id AS at_atendimento_cad_cliente_cartao_Id
FROM at_atendimento AS at_atendimento
left JOIN cad_cliente_cartao AS at_atendimento_cad_cliente_cartao ON at_atendimento_cad_cliente_cartao.Id = at_atendimento.cad_cliente_cartao_id
JOIN cad_cliente AS at_atendimento_cad_cliente_cartao_cad_cliente ON at_atendimento_cad_cliente_cartao_cad_cliente.Id = at_atendimento_cad_cliente_cartao.cad_cliente_id

no codigo acima eu faço a consulta na tabela "at_atendimento", faço um LEFT JOIN na tabela "cad_cliente_cartao" e dentro da tabela cad_cliente_cartao eu preciso fazer um join para buscar as informações da tabela "cad_cliente".

Até ai tudo bem. o problema:
quando os dados da tabela cad_cliente_cartao é null ele faz o join na tabela cad_cliente e consequentemente não retorna uma única linha, e eu preciso retornar as colunas com pelo menos os dados da tabela at_atendimento, é possível fazer isso?

estou usando PostgreSQL
Rodrigo

Rodrigo

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

20/05/2019

basta colocar um LEFT ao relacionar a tabela cad_cliente
SELECT 
	at_.Atendimento AS at_atendimento_Atendimento, 
	at_.Data AS at_atendimento_Data, 
	at_.fechado AS at_atendimento_fechado,
	at_.transmitido AS at_atendimento_transmitido,
	at_.Id AS at_atendimento_Id,
	at_cartao_cliente.Documento AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento,
	at_cartao_cliente.Documento2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento2,
	at_cartao_cliente.RazaoSocial AS at_atendimento_cad_cliente_cartao_cad_cliente_RazaoSocial,
	at_cartao_cliente.NomeFantasia AS at_atendimento_cad_cliente_cartao_cad_cliente_NomeFantasia,
	at_cartao_cliente.Cep AS at_atendimento_cad_cliente_cartao_cad_cliente_Cep,
	at_cartao_cliente.Endereco AS at_atendimento_cad_cliente_cartao_cad_cliente_Endereco,
	at_cartao_cliente.Numero AS at_atendimento_cad_cliente_cartao_cad_cliente_Numero,
	at_cartao_cliente.Complemento AS at_atendimento_cad_cliente_cartao_cad_cliente_Complemento,
	at_cartao_cliente.Bairro AS at_atendimento_cad_cliente_cartao_cad_cliente_Bairro, 
	at_cartao_cliente.Cidade AS at_atendimento_cad_cliente_cartao_cad_cliente_Cidade, 
	at_cartao_cliente.Estado AS at_atendimento_cad_cliente_cartao_cad_cliente_Estado, 
	at_cartao_cliente.RamoPrincipal AS at_atendimento_cad_cliente_cartao_cad_cliente_RamoPrincipal,
	at_cartao_cliente.Tel1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel1,
	at_cartao_cliente.Ramal1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal1,
	at_cartao_cliente.Tel2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel2, 
	at_cartao_cliente.Ramal2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal2,
	at_cartao_cliente.IsEmiteBoleto AS at_atendimento_cad_cliente_cartao_cad_cliente_IsEmiteBoleto,
	at_cartao_cliente.TipoDocumento AS at_atendimento_cad_cliente_cartao_cad_cliente_TipoDocumento,
	at_cartao_cliente.AutorizacaoLancamento AS at_atendimento_cad_cliente_cartao_cad_cliente_AutorizacaoLancamento, 
	at_cartao_cliente.Id AS at_atendimento_cad_cliente_cartao_cad_cliente_Id, 
	at_cartao.Cartao AS at_atendimento_cad_cliente_cartao_Cartao, 
	at_cartao.CodigoAdministrativo AS at_atendimento_cad_cliente_cartao_CodigoAdministrativo, 
	at_cartao.Contrato AS at_atendimento_cad_cliente_cartao_Contrato, 
	at_cartao.Validade AS at_atendimento_cad_cliente_cartao_Validade, 
	at_cartao.SigepUser AS at_atendimento_cad_cliente_cartao_SigepUser,
	at_cartao.SigepSenha AS at_atendimento_cad_cliente_cartao_SigepSenha,
	at_cartao.Descricao AS at_atendimento_cad_cliente_cartao_Descricao,
	at_cartao.desativado AS at_atendimento_cad_cliente_cartao_desativado,
	at_cartao.Id AS at_atendimento_cad_cliente_cartao_Id 
FROM
	at_atendimento AS at_
left JOIN
	cad_cliente_cartao AS at_cartao ON at_cartao.Id = at_.cad_cliente_cartao_id 
left JOIN
	cad_cliente AS at_cartao_cliente ON at_cartao_cliente.Id = at_cartao.cad_cliente_id
GOSTEI 0
Rodrigo

Rodrigo

20/05/2019

Sim fazendo esse LEFT "resolve o problema" porem se no dia de amanha eu precisar buscar esse campo como inner join, ele vai me trazer um valor null e eu vou ter que fazer verificações, fora isso ou eu coloco o LEFT ou vou ter que fazer 2 query?
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

20/05/2019

você pode tratar no where, indicando se algum campo da tabela e avaliando se é null.
algo assim:
where not (at_cartao_cliente.Id is null)

desta forma a query permanece igual e o "inner" é simulado no where.
GOSTEI 0
Willian Silva

Willian Silva

20/05/2019

Vou postar meu atual código, e depois vou explicar meu problema:

SELECT
at_atendimento.Atendimento AS at_atendimento_Atendimento,
at_atendimento.Data AS at_atendimento_Data,
at_atendimento.fechado AS at_atendimento_fechado,
at_atendimento.transmitido AS at_atendimento_transmitido,
at_atendimento.Id AS at_atendimento_Id,
at_atendimento_cad_cliente_cartao_cad_cliente.Documento AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento,
at_atendimento_cad_cliente_cartao_cad_cliente.Documento2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento2,
at_atendimento_cad_cliente_cartao_cad_cliente.RazaoSocial AS at_atendimento_cad_cliente_cartao_cad_cliente_RazaoSocial,
at_atendimento_cad_cliente_cartao_cad_cliente.NomeFantasia AS at_atendimento_cad_cliente_cartao_cad_cliente_NomeFantasia,
at_atendimento_cad_cliente_cartao_cad_cliente.Cep AS at_atendimento_cad_cliente_cartao_cad_cliente_Cep,
at_atendimento_cad_cliente_cartao_cad_cliente.Endereco AS at_atendimento_cad_cliente_cartao_cad_cliente_Endereco,
at_atendimento_cad_cliente_cartao_cad_cliente.Numero AS at_atendimento_cad_cliente_cartao_cad_cliente_Numero,
at_atendimento_cad_cliente_cartao_cad_cliente.Complemento AS at_atendimento_cad_cliente_cartao_cad_cliente_Complemento,
at_atendimento_cad_cliente_cartao_cad_cliente.Bairro AS at_atendimento_cad_cliente_cartao_cad_cliente_Bairro,
at_atendimento_cad_cliente_cartao_cad_cliente.Cidade AS at_atendimento_cad_cliente_cartao_cad_cliente_Cidade,
at_atendimento_cad_cliente_cartao_cad_cliente.Estado AS at_atendimento_cad_cliente_cartao_cad_cliente_Estado,
at_atendimento_cad_cliente_cartao_cad_cliente.RamoPrincipal AS at_atendimento_cad_cliente_cartao_cad_cliente_RamoPrincipal,
at_atendimento_cad_cliente_cartao_cad_cliente.Tel1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel1,
at_atendimento_cad_cliente_cartao_cad_cliente.Ramal1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal1,
at_atendimento_cad_cliente_cartao_cad_cliente.Tel2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel2,
at_atendimento_cad_cliente_cartao_cad_cliente.Ramal2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal2,
at_atendimento_cad_cliente_cartao_cad_cliente.IsEmiteBoleto AS at_atendimento_cad_cliente_cartao_cad_cliente_IsEmiteBoleto,
at_atendimento_cad_cliente_cartao_cad_cliente.TipoDocumento AS at_atendimento_cad_cliente_cartao_cad_cliente_TipoDocumento,
at_atendimento_cad_cliente_cartao_cad_cliente.AutorizacaoLancamento AS at_atendimento_cad_cliente_cartao_cad_cliente_AutorizacaoLancamento,
at_atendimento_cad_cliente_cartao_cad_cliente.Id AS at_atendimento_cad_cliente_cartao_cad_cliente_Id,
at_atendimento_cad_cliente_cartao.Cartao AS at_atendimento_cad_cliente_cartao_Cartao,
at_atendimento_cad_cliente_cartao.CodigoAdministrativo AS at_atendimento_cad_cliente_cartao_CodigoAdministrativo,
at_atendimento_cad_cliente_cartao.Contrato AS at_atendimento_cad_cliente_cartao_Contrato,
at_atendimento_cad_cliente_cartao.Validade AS at_atendimento_cad_cliente_cartao_Validade,
at_atendimento_cad_cliente_cartao.SigepUser AS at_atendimento_cad_cliente_cartao_SigepUser,
at_atendimento_cad_cliente_cartao.SigepSenha AS at_atendimento_cad_cliente_cartao_SigepSenha,
at_atendimento_cad_cliente_cartao.Descricao AS at_atendimento_cad_cliente_cartao_Descricao,
at_atendimento_cad_cliente_cartao.desativado AS at_atendimento_cad_cliente_cartao_desativado,
at_atendimento_cad_cliente_cartao.Id AS at_atendimento_cad_cliente_cartao_Id
FROM at_atendimento AS at_atendimento
left JOIN cad_cliente_cartao AS at_atendimento_cad_cliente_cartao ON at_atendimento_cad_cliente_cartao.Id = at_atendimento.cad_cliente_cartao_id
JOIN cad_cliente AS at_atendimento_cad_cliente_cartao_cad_cliente ON at_atendimento_cad_cliente_cartao_cad_cliente.Id = at_atendimento_cad_cliente_cartao.cad_cliente_id

no codigo acima eu faço a consulta na tabela "at_atendimento", faço um LEFT JOIN na tabela "cad_cliente_cartao" e dentro da tabela cad_cliente_cartao eu preciso fazer um join para buscar as informações da tabela "cad_cliente".

Até ai tudo bem. o problema:
quando os dados da tabela cad_cliente_cartao é null ele faz o join na tabela cad_cliente e consequentemente não retorna uma única linha, e eu preciso retornar as colunas com pelo menos os dados da tabela at_atendimento, é possível fazer isso?

estou usando PostgreSQL


Acho que poderia verificar a sua regra de negocio, acho que todo atendimento, tem um cliente e esse cliente pode ou não ter um cartão, acho que o relacionamento assim seria até melhor para futuros consultas e relatórios.

O trabalho pode ser maior mais para um futuro próximo você vai ver que vai ter muito mais vantagem esse tipo de relacionamento.
GOSTEI 0
Rodrigo

Rodrigo

20/05/2019

a questão que o cliente pode ter varios cartoes, por isso estou colocando ali, não seria o ideal?
GOSTEI 0
Willian Silva

Willian Silva

20/05/2019

a questão que o cliente pode ter vários cartões, por isso estou colocando ali, não seria o ideal?


Pega o cliente relacionado pelo atendimento, e também pode pega o cartão do cliente relacionado ao atendimento, só na tela do atendimento ao selecionar um cliente, ele carrega os cartões caso o cliente tenha para que seja vinculado ao atendimento o cliente e o cartão do mesmo.
GOSTEI 0
Rodrigo

Rodrigo

20/05/2019

a questão que o cliente pode ter vários cartões, por isso estou colocando ali, não seria o ideal?


Pega o cliente relacionado pelo atendimento, e também pode pega o cartão do cliente relacionado ao atendimento, só na tela do atendimento ao selecionar um cliente, ele carrega os cartões caso o cliente tenha para que seja vinculado ao atendimento o cliente e o cartão do mesmo.


mas é isso que esta fazendo, nesse momento eu estou carregando o atendimento inteiro para dar prosseguimento no que preciso
GOSTEI 0
Willian Silva

Willian Silva

20/05/2019

a questão que o cliente pode ter vários cartões, por isso estou colocando ali, não seria o ideal?


Pega o cliente relacionado pelo atendimento, e também pode pega o cartão do cliente relacionado ao atendimento, só na tela do atendimento ao selecionar um cliente, ele carrega os cartões caso o cliente tenha para que seja vinculado ao atendimento o cliente e o cartão do mesmo.


mas é isso que esta fazendo, nesse momento eu estou carregando o atendimento inteiro para dar prosseguimento no que preciso


Sim mais você esta buscando o cliente pelo cartão.

A ideia é busca o cliente pelo atendimento e o cartão do cliente pelo atendimento o código de vinculado dessas duas informações tem que está gravada no atendimento.
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

20/05/2019

o que o Willian Silva está dizendo é que o relacionamento deveria ser ATENDIMENTO, CLIENTE, CARTÃO.
Porque o atendimento precisa ser para um cliente. Não pode existir um atendimento sem um cliente, certo? Agora o cartão não é obrigatório. Então o relacionamento mudaria um pouco:
SELECT
	atend.Atendimento AS at_atendimento_Atendimento, 
	atend.Data AS at_atendimento_Data, 
	atend.fechado AS at_atendimento_fechado,
	atend.transmitido AS at_atendimento_transmitido,
	atend.Id AS at_atendimento_Id,
	cliente.Documento AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento,
	cliente.Documento2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Documento2,
	cliente.RazaoSocial AS at_atendimento_cad_cliente_cartao_cad_cliente_RazaoSocial,
	cliente.NomeFantasia AS at_atendimento_cad_cliente_cartao_cad_cliente_NomeFantasia,
	cliente.Cep AS at_atendimento_cad_cliente_cartao_cad_cliente_Cep,
	cliente.Endereco AS at_atendimento_cad_cliente_cartao_cad_cliente_Endereco,
	cliente.Numero AS at_atendimento_cad_cliente_cartao_cad_cliente_Numero,
	cliente.Complemento AS at_atendimento_cad_cliente_cartao_cad_cliente_Complemento,
	cliente.Bairro AS at_atendimento_cad_cliente_cartao_cad_cliente_Bairro, 
	cliente.Cidade AS at_atendimento_cad_cliente_cartao_cad_cliente_Cidade, 
	cliente.Estado AS at_atendimento_cad_cliente_cartao_cad_cliente_Estado, 
	cliente.RamoPrincipal AS at_atendimento_cad_cliente_cartao_cad_cliente_RamoPrincipal,
	cliente.Tel1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel1,
	cliente.Ramal1 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal1,
	cliente.Tel2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Tel2, 
	cliente.Ramal2 AS at_atendimento_cad_cliente_cartao_cad_cliente_Ramal2,
	cliente.IsEmiteBoleto AS at_atendimento_cad_cliente_cartao_cad_cliente_IsEmiteBoleto,
	cliente.TipoDocumento AS at_atendimento_cad_cliente_cartao_cad_cliente_TipoDocumento,
	cliente.AutorizacaoLancamento AS at_atendimento_cad_cliente_cartao_cad_cliente_AutorizacaoLancamento, 
	cliente.Id AS at_atendimento_cad_cliente_cartao_cad_cliente_Id, 
	cartao.Cartao AS at_atendimento_cad_cliente_cartao_Cartao, 
	cartao.CodigoAdministrativo AS at_atendimento_cad_cliente_cartao_CodigoAdministrativo, 
	cartao.Contrato AS at_atendimento_cad_cliente_cartao_Contrato, 
	cartao.Validade AS at_atendimento_cad_cliente_cartao_Validade, 
	cartao.SigepUser AS at_atendimento_cad_cliente_cartao_SigepUser,
	cartao.SigepSenha AS at_atendimento_cad_cliente_cartao_SigepSenha,
	cartao.Descricao AS at_atendimento_cad_cliente_cartao_Descricao,
	cartao.desativado AS at_atendimento_cad_cliente_cartao_desativado,
	cartao.Id AS at_atendimento_cad_cliente_cartao_Id 
FROM
	at_atendimento AS atend
inner JOIN -- INNER supondo que um atendimento SEMPRE tem um cliente relacionado a ele
	cad_cliente AS cliente ON cliente.Id = atend.cad_cliente_id
left JOIN -- LEFT supondo que um atendimento/cliente NEM SEMPRE terá um cartão associado a ele
	cad_cliente_cartao AS cartao ON cartao.cad_cliente_id = cliente.id
	and cartao.Id = atend.cad_cliente_cartao_id -- esta informação parte mesmo do atendimento?
GOSTEI 0
Rodrigo

Rodrigo

20/05/2019

Entendi, é que eu só postei parte do codigo para nao ficar muito grande, na verdade dentro do atendimento tem o cliente, o cartao e o departamento, porem como não existe um cartao sem o cliente, dentro do cartao eh carregado o clliente também, eu estou desenvolvendo um DLL que faz tudo isso pra mim de forma automatica, então consequentemente ele acaba carregando o cliente dentro do cartao tb
GOSTEI 0
POSTAR