Usuário com melhor resposta
Left Join não funciona

Pergunta
-
Prezados,
tenho uma consulta no Sql Server 2012 que realiza um join entre duas tabelas. A primeira é a tabela de item com 21 registros, a segunda é a de lançamentos. Como quero retornar todos os itens que tiveram ou não lançamentos em um determinado mês montei a consulta abaixo, porém a consulta retorna somente 12 linhas quando o correto seria 21, pois esta é a quantidade de itens na tabela de itens. O que pode estar acontecendo?
select
I.ID_ITEM, sum(IsNull(L.VALOR,0)) as Valor
from
ITEM I LEFT JOIN
LANCAMENTO L ON I.ID_ITEM = L.ID_ITEM
where
Year(L.DT_PAGAMENTO) = 2015 and
Month(L.DT_PAGAMENTO) = 1
group by I.ID_ITEM
Respostas
-
Olá!
Provavelmente os dados estão sendo restringidos por causa do conteúdo na cláusula where. Por mais que você utilize um left join, quando esta tabela é apontada na cláusula where, o efeito fica semelhante ao de um inner join. Tente o seguinte:
select I.ID_ITEM, sum(IsNull(L.VALOR,0)) as Valor from ITEM I LEFT JOIN LANCAMENTO L ON I.ID_ITEM = L.ID_ITEM and Year(L.DT_PAGAMENTO) = 2015 and Month(L.DT_PAGAMENTO) = 1 group by I.ID_ITEM
Bom trabalho!
- Marcado como Resposta Mauro Magalhães segunda-feira, 1 de junho de 2015 11:58
Todas as Respostas
-
Mauro,
faça a pesquisa somente na tabela lançamento considerando os parametros de year e month e verifique se não são eles que estão filtrando os dados.
select distinct lancamento.Id_item from lancamento where year(lancamento.Dt_pagamento) = 2015 and month(lancamento.dt_pagamento) = 1
Natan
-
Olá!
Provavelmente os dados estão sendo restringidos por causa do conteúdo na cláusula where. Por mais que você utilize um left join, quando esta tabela é apontada na cláusula where, o efeito fica semelhante ao de um inner join. Tente o seguinte:
select I.ID_ITEM, sum(IsNull(L.VALOR,0)) as Valor from ITEM I LEFT JOIN LANCAMENTO L ON I.ID_ITEM = L.ID_ITEM and Year(L.DT_PAGAMENTO) = 2015 and Month(L.DT_PAGAMENTO) = 1 group by I.ID_ITEM
Bom trabalho!
- Marcado como Resposta Mauro Magalhães segunda-feira, 1 de junho de 2015 11:58
-
Obrigado!
Eu também já tentei deste forma e não funcionou. Com certeza é a cláusula where, porém acredito que isso não deveria ocorrer. Acredito que o otimizador deveria filtrar os lançamentos e depois fazer o left join. Da forma como está o left join não está servindo de nada.
-
Bom dia,
Acredito que você conseguiria obter o resultado desejado com a sugestão do Rodrigo.
De qualquer forma, seguem mais 2 sugestões para teste:
with CTE_Sum as ( select ID_ITEM, sum(VALOR) as Valor from LANCAMENTO where Year(DT_PAGAMENTO) = 2015 and Month(DT_PAGAMENTO) = 1 ) select I.ID_ITEM, IsNull(L.VALOR, 0) as Valor from ITEM I LEFT JOIN CTE_Sum L ON I.ID_ITEM = L.ID_ITEM
select I.ID_ITEM, sum(IsNull(L.VALOR,0)) as Valor from ITEM I LEFT JOIN LANCAMENTO L ON I.ID_ITEM = L.ID_ITEM where (Year(L.DT_PAGAMENTO) = 2015 and Month(L.DT_PAGAMENTO) = 1) or (L.DT_PAGAMENTO IS NULL) group by I.ID_ITEM
Espero que ajude.
Assinatura: http://www.imoveisemexposicao.com.br
-
-
-
Olá novamente, Mauro!
Curioso não ter funcionado da forma que sugeri. Montei um pequeno cenário, e funcionou perfeitamente, exceto quando forcei uma entrada de data em um formato de cultura diferente da definida no banco de dados (como inserir data "17/01/2015" quando deveria ser "2015/01/17", por exemplo, o que faria os registros com data errada serem ignorados). Será que não é uma situação semelhante a esta que está te passando a perna?
Bom trabalho!
-
Eu consegui fazer de uma forma bem parecida com a sua, através de subselect e funcionou. As datas estão inseridas normalmente na base de dados. Eu esperava que a clasula where não interferisse na junção. Imaginava que o Sql Server resolvesse primeiro o filtro para depois resolver a junção. Em outros SGDB´s funciona normalmente. Mas de qualquer forma o importante aqui é obter o resultado desejado. Agradeço a todos pela força!!!!
-
Eu consegui fazer de uma forma bem parecida com a sua, através de subselect e funcionou. As datas estão inseridas normalmente na base de dados. Eu esperava que a clasula where não interferisse na junção. Imaginava que o Sql Server resolvesse primeiro o filtro para depois resolver a junção. Em outros SGDB´s funciona normalmente. Mas de qualquer forma o importante aqui é obter o resultado desejado. Agradeço a todos pela força!!!!
Beleza, Mauro!
Que bom que conseguiu. Sugiro que você post a sua solução e a marque como resposta, pois poderá ajudar outras pessoas com problema semelhante.
-
-
Ficou como uma variação a query do José. Mais uma forma de fazer. E quero me desculpar com o Rodrigo pois a query dele funciona sim e é mais simples. Mais uma vez muito obrigado a todos!!!
Eis o código:
SELECT
I.NM_ITEM, Isnull(Z.Valor,0)
FROM
ITEM I LEFT JOIN
(
SELECT
L.ID_ITEM, SUM(IsNull(L.VALOR,0)) as ValorFROM
LANCAMENTO L
WHERE
Year(L.DT_PAGAMENTO) = @ano and
Month(L.DT_PAGAMENTO) = @mes
group by L.ID_ITEM ) Z ON I.ID_ITEM = Z.ID_ITEMORDER BY i.NM_ITEM
-
Obrigado!
Eu também já tentei deste forma e não funcionou. Com certeza é a cláusula where, porém acredito que isso não deveria ocorrer. Acredito que o otimizador deveria filtrar os lançamentos e depois fazer o left join. Da forma como está o left join não está servindo de nada.
Mauro,
Diferente da instrução INNER JOIN, as instruções "OUTER JOIN" (LEFT, RIGHT, FULL e CROSS) possuem um critério onde o otimizador da consulta não tenta reorganizar a ordem de vínculo das tabelas para execução do OUTER JOIN (como ocorre no INNER JOIN).
A tabela da "esquerda" em LEFT OUTER JOIN é acessada primeiro, seguida pela tabela "direita". Essa ordem de vínculo fixo pode levar à planos de execução de "qualidade inferior".
O Mecanismo dos Bancos de Dados no SQL Server também possuem uma ordem de processamento lógico que prioriza a execução do "JOIN" (no seu caso o LEFT) e só depois "filtra" através do comando "WHERE".
Apenas para esclarecimento, a Ordem de Processamento lógico de instrução qualquer consulta T-SQL é a seguinte:
- FROM
- ON
- JOIN
- WHERE
- GROUP BY
- WITH CUBE OU WITH ROLLUP
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- TOP
Para maiores informações veja:
https://technet.microsoft.com/pt-br/library/ms172984%28v=sql.110%29.aspx
https://msdn.microsoft.com/pt-br/library/ms189499.aspx
Se ajudou na sua solução, não esqueça de marcar como resposta !
Abraços,
Durval Ramos
Microsoft Partner | MTA | MCSA - SQL Server 2012 | MCSE - Data Platform
----------------------------------
Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil" -