none
Uso de 3 Tabelas no LEFT JOIN

    Question

  • Olá pessoal,

     

    Antigamente utilizava um banco MySQL onde a seguinte instrução era possível:

     

    FROM parcelas, dividas, campanhas, clientes, devedores, acordos_parcelas, tipo_forma, recibos, temp_counter     
     LEFT JOIN credito_anterior ON dividas.id = credito_anterior.divida AND recibos.id = credito_anterior.recibo    
     LEFT JOIN credito_restante ON dividas.id = credito_restante.divida AND recibos.id = credito_restante.recibo  

     

    Agora após migrar para o banco de dados SQL SERVER 2005, vejo que não é possível executar este comando, alguém poderia me dar uma dica de como resolver este problema, pois já tentei diversas formas e não consigo desenvolver uma Query que retorne o resultado em SQL Server que estava retornando em MySQL.

     

    Grato, Thiago!

    Wednesday, February 06, 2008 8:21 PM

All replies

  • Boa Tarde,

     

    É preciso uma certa cautela, pois, em certas circunstâncias, o resultado esperado não é semanticamente o correto. A utilização dos operadores LEFT e RIGHT possui certas particularidades que ficam ocultas na maioria dos casos, mas em determinadas situações podem trazer alguns efeitos inesperados.

     

    Não gostaria de me ater a uma longa e vaga explanação (pode ser que o seu problema seja muito menor do que eu estou supondo). Você poderia postar um exemplo mais concreto do porque o MySQL e o SQL Server estão divergindo ?

     

    [ ]s,

     

    Gustavo

    Wednesday, February 06, 2008 9:20 PM
    Moderator
  •  

    Olá Gustavo,

     

    Estarei postando aqui o exemplo geral de meu problema, esse select que você está vendo logo abaixo está correto e funciona perfeitamente no Banco MySQL:

     

    SELECT

    temp_counter.counter AS counter ,

    parcelas.id AS parcelas_id ,

    parcelas.status AS parcelas_status ,

    parcelas.recibo AS parcelas_recibo ,

    parcelas.vencimento AS parcelas_vencimento ,

    parcelas.baixa AS parcelas_baixa ,

    parcelas.descricao AS parcelas_descricao ,

    parcelas.valor + 0 AS parcelas_valor ,

    parcelas.correcao + 0 AS parcelas_correcao ,

    parcelas.multa + 0 AS parcelas_multa ,

    parcelas.juros + 0 AS parcelas_juros ,

    parcelas.taxa + 0 AS parcelas_taxa ,

    parcelas.honorarios + 0 AS parcelas_honorarios ,

    parcelas.desconto + 0 AS parcelas_desconto ,

    parcelas.posacordo + 0 AS parcelas_posacordo ,

    dividas.id AS dividas_id ,

    dividas.nome AS dividas_nome ,

    dividas.descricao AS dividas_descricao ,

    dividas.contrato AS dividas_contrato ,

    clientes.id AS clientes_id ,

    clientes.nomefantasia AS clientes_nomefantasia ,

    clientes.razaosocial AS clientes_razaosocial ,

    devedores.id AS devedores_id ,

    devedores.nome AS devedores_nome ,

    devedores.cpf AS devedores_cpf ,

    acordos_parcelas.pagamento AS acordos_parcelas_pagamento ,

    acordos_parcelas.credito AS acordos_parcelas_credito ,

    acordos_parcelas.cheque AS acordos_parcelas_cheque ,

    acordos_parcelas.banco AS acordos_parcelas_banco ,

    acordos_parcelas.praca AS acordos_parcelas_praca ,

    tipo_forma.descricao AS tipo_forma ,

    ISNULL(cast(credito_anterior.valor as decimal(10,2)),0) AS credito_anterior ,

    ISNULL(cast(credito_restante.valor as decimal(10,2)),0) AS credito_restante ,

    '' AS extenso ,

    '' AS judicial_processo ,

    '' AS judicial_vara

    FROM parcelas, campanhas, clientes, devedores, acordos_parcelas, tipo_forma, temp_counter, recibos, dividas

    LEFT JOIN credito_anterior ON dividas.id = credito_anterior.divida AND recibos.id = credito_anterior.recibo

    LEFT JOIN credito_restante ON dividas.id = credito_restante.divida AND recibos.id = credito_restante.recibo

    WHERE parcelas.divida = dividas.id

    AND dividas.campanha = campanhas.id

    AND campanhas.cliente = clientes.id

    AND dividas.devedor = devedores.id

    AND acordos_parcelas.id = recibos.acordo_parcela

    AND recibos.id = parcelas.recibo

    AND acordos_parcelas.forma = tipo_forma.id

    AND parcelas.recibo = 329312

     

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Os LEFT JOIN que estão em negrito ao usar o AND para relacionar as tabelas Credito_Anterior, Dividas e Recibos nao mais funciona ao executar o mesmo em SQL Server, ao executar ele mostra o seguinte erro:

     

    Msg 4104, Level 16, State 1, Line 1

    The multi-part identifier "recibos.id" could not be bound.

     

    Ao colocar a tabela RECIBO em ultimo lugar no FROM ele retorna o seguinte erro:

     

    Msg 4104, Level 16, State 1, Line 1

    The multi-part identifier "dividas.id" could not be bound.

     

    Não sei como solucionar esse problema, estarei grato em me ajudar.

    [ ]´s Thiago.

    Thursday, February 07, 2008 11:11 AM
  • Thiago,

     

    Já tentou atribui apelidos para suas tables no Join ao invês de ficar sempre declarado todo o nome do objeto?

    Thursday, February 07, 2008 12:23 PM
  • Ja sim, dá na mesma.

    Thursday, February 07, 2008 12:26 PM
  • Thiago,

     

    Eu já presenciei alguns problemas entre o MySQL e o SQL Server na utilização de Joins!!!

     

    Veja se assim funciona:

     

    Code Snippet

    SELECT

    t.counter AS counter ,

    p.id AS p_id ,

    p.status AS p_status ,

    p.recibo AS p_recibo ,

    p.vencimento AS p_vencimento ,

    p.baixa AS p_baixa ,

    p.descricao AS p_descricao ,

    p.valor + 0 AS p_valor ,

    p.correcao + 0 AS p_correcao ,

    p.multa + 0 AS p_multa ,

    p.juros + 0 AS p_juros ,

    p.taxa + 0 AS p_taxa ,

    p.honorarios + 0 AS p_honorarios ,

    p.desconto + 0 AS p_desconto ,

    p.posacordo + 0 AS p_posacordo ,

    d.id AS d_id ,

    d.nome AS d_nome ,

    d.descricao AS d_descricao ,

    d.contrato AS d_contrato ,

    cli.id AS cli_id ,

    cli.nomefantasia AS cli_nomefantasia ,

    cli.razaosocial AS cli_razaosocial ,

    dv.id AS dv_id ,

    dv.nome AS dv_nome ,

    dv.cpf AS dv_cpf ,

    ac_p.pagamento AS ac_p_pagamento ,

    ac_p.credito AS ac_p_credito ,

    ac_p.cheque AS ac_p_cheque ,

    ac_p.banco AS ac_p_banco ,

    ac_p.praca AS ac_p_praca ,

    tipo_forma.descricao AS tipo_forma ,

    ISNULL(cast(crda.valor as decimal(10,2)),0) AS crda ,

    ISNULL(cast(credito_restante.valor as decimal(10,2)),0) AS credito_restante ,

    '' AS extenso ,

    '' AS judicial_processo ,

    '' AS judicial_vara

    FROM parcelas p, campanhas c, clientes cli, devedores dv, acordos_parcelas ac, tipo_forma tf, temp_counter t, recibos r, dividas d

    LEFT JOIN credito_anterior crda ON d.id = crda.divida AND r.id = crda.recibo

    LEFT JOIN credito_restante crdr ON d.id = crdr.divida AND r.id = crdr.recibo

    WHERE p.divida = d.id

    AND d.campanha = c.id

    AND c.cliente = cli.id

    AND d.devedor = dv.id

    AND ac_p.id = racordo_parcela

    AND r.id = p.recibo

    AND ac_p.forma = tf.id

    AND p.recibo = 329312

     

     

    Thursday, February 07, 2008 12:31 PM
  • Olá Thiago,

     

    Estou vendo que você está fazendo o JOIN de duas formas (uma via operador OUTER e outra via cláusula WHERE). Existe alguma razão para misturar essas junções ? Não seria melhor escolher uma única forma para montar esse JOIN (Sugiro o LEFT OUTER JOIN) ? Creio que isso possa influenciar o resultado ainda que indiretamente.

     

    [ ]s,

     

    Gustavo

     

    Thursday, February 07, 2008 12:36 PM
    Moderator
  • Olá gustavo,

     

    Tentei executar o SQL desta maneira, onde o resultado esperado foi mostrado:

     

    SELECT

    temp_counter.counter AS counter ,

    parcelas.id AS parcelas_id ,

    parcelas.status AS parcelas_status ,

    parcelas.recibo AS parcelas_recibo ,

    parcelas.vencimento AS parcelas_vencimento ,

    parcelas.baixa AS parcelas_baixa ,

    parcelas.descricao AS parcelas_descricao ,

    Cast(parcelas.valor as Money) + 0 AS parcelas_valor ,

    Cast(parcelas.correcao as Money) + 0 AS parcelas_correcao ,

    Cast(parcelas.multa as Money) + 0 AS parcelas_multa ,

    Cast(parcelas.juros as Money) + 0 AS parcelas_juros ,

    Cast(parcelas.taxa as Money) + 0 AS parcelas_taxa ,

    Cast(parcelas.honorarios as Money) + 0 AS parcelas_honorarios ,

    Cast(parcelas.desconto as Money) + 0 AS parcelas_desconto ,

    Cast(parcelas.posacordo as Money) + 0 AS parcelas_posacordo ,

    dividas.id AS dividas_id ,

    dividas.nome AS dividas_nome ,

    dividas.descricao AS dividas_descricao ,

    dividas.contrato AS dividas_contrato ,

    clientes.id AS clientes_id ,

    clientes.nomefantasia AS clientes_nomefantasia ,

    clientes.razaosocial AS clientes_razaosocial ,

    devedores.id AS devedores_id ,

    devedores.nome AS devedores_nome ,

    devedores.cpf AS devedores_cpf ,

    acordos_parcelas.pagamento AS acordos_parcelas_pagamento ,

    acordos_parcelas.credito AS acordos_parcelas_credito ,

    acordos_parcelas.cheque AS acordos_parcelas_cheque ,

    acordos_parcelas.banco AS acordos_parcelas_banco ,

    acordos_parcelas.praca AS acordos_parcelas_praca ,

    tipo_forma.descricao AS tipo_forma ,

    ISNULL(cast(credito_anterior.valor as decimal(10,2)),0) AS credito_anterior ,

    ISNULL(cast(credito_restante.valor as decimal(10,2)),0) AS credito_restante ,

    '' AS extenso ,

    '' AS judicial_processo ,

    '' AS judicial_vara

    FROM (recibos

    LEFT OUTER JOIN credito_anterior ON recibos.id = credito_anterior.recibo

    LEFT OUTER JOIN credito_restante ON recibos.id = credito_restante.recibo

    LEFT OUTER JOIN parcelas ON parcelas.recibo = recibos.id),

    campanhas, clientes, devedores, acordos_parcelas, tipo_forma, temp_counter, dividas

    WHERE parcelas.divida = dividas.id

    AND dividas.campanha = campanhas.id

    AND campanhas.cliente = clientes.id

    AND dividas.devedor = devedores.id

    AND acordos_parcelas.id = recibos.acordo_parcela

    AND acordos_parcelas.forma = tipo_forma.id

    AND parcelas.recibo = 329312

     

    Porém, em 2 linhas das 4 retornadas os valores dos campos credito_anterior.valor e credito_restante.valor deveriam vir ZERADOS, onde nao ocorreu, acredito que devo estar unindo tabelas de maneira errada.

    Thursday, February 07, 2008 12:41 PM
  • Olá Thiago,

     

    Existem alguns detalhes que podem fazer a diferença na forma como são unidas as tabelas em JOINs e em cláusulas WHERE. Minha primeira recomendação é que você adote o uso de operadores LEFT e INNER para todas as tabelas envolvidas. Unir parcialmente com os operadores JOIN e com a cláusula WHERE torna a sentença SQL mais confusa, sujeita a erros e difícil de debugar.

     

    Depois que isso for feito, fica um pouco mais fácil de "achar" a divergência entre o SQL Server o MySQL

     

    [ ]s,

     

    Gustavo

     

     

     

    Thursday, February 07, 2008 12:51 PM
    Moderator
  • Thiago, pelo visto você está fazendo um LEFT JOIN e fazendo um AND entre duas tabelas que inicialmente não estavam envolvidas nesse LEFT JOIN.

     

    Existe alguma relação entre as tabelas envolvidas no LEFT JOIN e as fora do JOIN? Caso sim acho que seria interessante você especificar, caso contrário, você pode deixar isso do lado de fora como fez no WHERE.

     

    Pelo visto o SQL Server está se perdendo no momento de construir essa junção, no plano de execução deve estar caindo num Hash Join.

     

    Code Snippet

    SELECT

    temp_counter.counter AS counter ,

    parcelas.id AS parcelas_id ,

    parcelas.status AS parcelas_status ,

    parcelas.recibo AS parcelas_recibo ,

    parcelas.vencimento AS parcelas_vencimento ,

    parcelas.baixa AS parcelas_baixa ,

    parcelas.descricao AS parcelas_descricao ,

    parcelas.valor + 0 AS parcelas_valor ,

    parcelas.correcao + 0 AS parcelas_correcao ,

    parcelas.multa + 0 AS parcelas_multa ,

    parcelas.juros + 0 AS parcelas_juros ,

    parcelas.taxa + 0 AS parcelas_taxa ,

    parcelas.honorarios + 0 AS parcelas_honorarios ,

    parcelas.desconto + 0 AS parcelas_desconto ,

    parcelas.posacordo + 0 AS parcelas_posacordo ,

    dividas.id AS dividas_id ,

    dividas.nome AS dividas_nome ,

    dividas.descricao AS dividas_descricao ,

    dividas.contrato AS dividas_contrato ,

    clientes.id AS clientes_id ,

    clientes.nomefantasia AS clientes_nomefantasia ,

    clientes.razaosocial AS clientes_razaosocial ,

    devedores.id AS devedores_id ,

    devedores.nome AS devedores_nome ,

    devedores.cpf AS devedores_cpf ,

    acordos_parcelas.pagamento AS acordos_parcelas_pagamento ,

    acordos_parcelas.credito AS acordos_parcelas_credito ,

    acordos_parcelas.cheque AS acordos_parcelas_cheque ,

    acordos_parcelas.banco AS acordos_parcelas_banco ,

    acordos_parcelas.praca AS acordos_parcelas_praca ,

    tipo_forma.descricao AS tipo_forma ,

    ISNULL(cast(credito_anterior.valor as decimal(10,2)),0) AS credito_anterior ,

    ISNULL(cast(credito_restante.valor as decimal(10,2)),0) AS credito_restante ,

    '' AS extenso ,

    '' AS judicial_processo ,

    '' AS judicial_vara

    FROM parcelas, campanhas, clientes, devedores, acordos_parcelas, tipo_forma, temp_counter, recibos, dividas

    LEFT JOIN credito_anterior ON dividas.id = credito_anterior.divida

    LEFT JOIN credito_restante ON dividas.id = credito_restante.divida

    WHERE parcelas.divida = dividas.id

    AND recibos.id = credito_anterior.recibo  

    AND recibos.id = credito_restante.recibo

    AND dividas.campanha = campanhas.id

    AND campanhas.cliente = clientes.id

    AND dividas.devedor = devedores.id

    AND acordos_parcelas.id = recibos.acordo_parcela

    AND recibos.id = parcelas.recibo

    AND acordos_parcelas.forma = tipo_forma.id

    AND parcelas.recibo = 329312

     

     

    Veja se essa construção funciona, ok? Nos retorne em caso de erro.

     

    Abraços,

    Thursday, February 07, 2008 2:39 PM
  • Thiago,

     

    O ideal é que você usasse

     

    Code Snippet

    FROM parcelas

    INNER JOIN dividas

    ON xxxxxxxxxxxxx = yyyyyyyyyyyy

    INNER JOIN campanhas

    ON xxxxxxxxxxxxx = yyyyyyyyyyyy

    INNER JOIN clientes

    ON xxxxxxxxxxxxx = yyyyyyyyyyyy

    ETC ETC

     LEFT JOIN credito_anterior ON dividas.id = credito_anterior.divida AND recibos.id = credito_anterior.recibo    
     LEFT JOIN credito_restante ON dividas.id = credito_restante.divida AND recibos.id = credito_restante.recibo  

     

     thiagorcunha wrote:

    Olá pessoal,

     

    Antigamente utilizava um banco MySQL onde a seguinte instrução era possível:

     

     

    Agora após migrar para o banco de dados SQL SERVER 2005, vejo que não é possível executar este comando, alguém poderia me dar uma dica de como resolver este problema, pois já tentei diversas formas e não consigo desenvolver uma Query que retorne o resultado em SQL Server que estava retornando em MySQL.

     

    Grato, Thiago!

Thursday, February 07, 2008 3:37 PM
  • Olá Sergio,

     

    Obrigado pela ajuda, e deixo aqui meu agradecimento a todos aqueles que tentaram me ajudar. Aprendi muito aqui neste forum que encontei ontem mesmo, pesquisando na WEB. Estarei aqui mais vezes para aprender mais e passar um pouco que sei a outras pessoas. Ao utilizando o INNER JOIN dividas, consegui o resultado que esperava.

     

     

    Grato a todos.

     

    [ ]´s Thiago.

    Thursday, February 07, 2008 4:02 PM
  • Olá Thiago,

     

    Que bom que em conjunto conseguimos dar as sugestões para que você resolvesse o seu problema (estamos aqui para isso). Fique à vontade para postar suas dúvidas. Tentaremos ajudá-los sempre que possível. Seria bom apenas que você classificasse as respostas. Serve de estímulo e feedback.

     

    [ ]s,

     

    Gustavo

     

    Thursday, February 07, 2008 4:08 PM
    Moderator
  • Olá Gustavo,

     

     

    Claro, estarei aqui postando como ficou o SQL final, que com a ajuda de todos solucionei o problema:

     

    SELECT

    temp_counter.counter AS counter ,

    parcelas.id AS parcelas_id ,

    parcelas.status AS parcelas_status ,

    parcelas.recibo AS parcelas_recibo ,

    parcelas.vencimento AS parcelas_vencimento ,

    parcelas.baixa AS parcelas_baixa ,

    parcelas.descricao AS parcelas_descricao ,

    Cast(parcelas.valor as Money) + 0 AS parcelas_valor ,

    Cast(parcelas.correcao as Money) + 0 AS parcelas_correcao ,

    Cast(parcelas.multa as Money) + 0 AS parcelas_multa ,

    Cast(parcelas.juros as Money) + 0 AS parcelas_juros ,

    Cast(parcelas.taxa as Money) + 0 AS parcelas_taxa ,

    Cast(parcelas.honorarios as Money) + 0 AS parcelas_honorarios ,

    Cast(parcelas.desconto as Money) + 0 AS parcelas_desconto ,

    Cast(parcelas.posacordo as Money) + 0 AS parcelas_posacordo ,

    dividas.id AS dividas_id ,

    dividas.nome AS dividas_nome ,

    dividas.descricao AS dividas_descricao ,

    dividas.contrato AS dividas_contrato ,

    clientes.id AS clientes_id ,

    clientes.nomefantasia AS clientes_nomefantasia ,

    clientes.razaosocial AS clientes_razaosocial ,

    devedores.id AS devedores_id ,

    devedores.nome AS devedores_nome ,

    devedores.cpf AS devedores_cpf ,

    acordos_parcelas.pagamento AS acordos_parcelas_pagamento ,

    acordos_parcelas.credito AS acordos_parcelas_credito ,

    acordos_parcelas.cheque AS acordos_parcelas_cheque ,

    acordos_parcelas.banco AS acordos_parcelas_banco ,

    acordos_parcelas.praca AS acordos_parcelas_praca ,

    tipo_forma.descricao AS tipo_forma ,

    ISNULL(cast(credito_anterior.valor as decimal(10,2)),0) AS credito_anterior ,

    ISNULL(cast(credito_restante.valor as decimal(10,2)),0) AS credito_restante ,

    '' AS extenso ,

    '' AS judicial_processo ,

    '' AS judicial_vara

    FROM

    temp_counter, parcelas

    INNER JOIN dividas

    ON parcelas.divida = dividas.id

    INNER JOIN campanhas

    ON dividas.campanha = campanhas.id

    INNER JOIN clientes

    ON campanhas.cliente = clientes.id

    INNER JOIN devedores

    ON dividas.devedor = devedores.id

    INNER JOIN recibos

    ON recibos.id = parcelas.recibo

    INNER JOIN acordos_parcelas

    ON acordos_parcelas.id = recibos.acordo_parcela

    INNER JOIN tipo_forma

    ON acordos_parcelas.forma = tipo_forma.id

    LEFT JOIN credito_anterior ON dividas.id = credito_anterior.divida AND recibos.id = credito_anterior.recibo

    LEFT JOIN credito_restante ON dividas.id = credito_restante.divida AND recibos.id = credito_restante.recibo

    WHERE

    parcelas.recibo = 329312

     

     

    Ao tirar as ligações do WHERE o SQL SERVER conseguiu (acredito eu, depois de tanto tentar), utilizar as 3 tabelas que já constavam anteriormente utilizando o comando INNER JOIN e fazendo com que executasse sem qualquer problema, retornando assim o resultado esperado.

     

    Obrigado a todos aí pela ajuda e paciência.

    Thursday, February 07, 2008 4:14 PM
  • Boa noite.

    Acredito que esta vídeo aula vai tirar grande parte das suas dúvidas.

    URL: http://youtu.be/f5DmoEpqJCs

    []´s


    Drausio Henrique Chiarotti

    Wednesday, September 11, 2013 2:32 AM