none
Ajuda com query RRS feed

  • Pergunta

  • Caros, bom dia. 

    Estou penando para conseguir o resultado correto de uma query. Seguem detalhes:

    Tenho as tabelas COLABORADOR, AFASTAMENTO, PROJETO, DIASUTEIS, VR_COLABORADOR, VALE_REFEICAO, HISTORICO

    A tabela COLABORADOR tem 200 registros. Já as outras, depende do que for lançado. 

    O resultado que preciso na query é:
    200 linhas (uma para cada colaborador), e o colaborador que não tiver dado lançado nas outras tabelas aparecer NULL ou algo do tipo, ao invés de não aparecer. Deu pra entender?

    Segue query até agora, mas só aparece o pessoal que tem algum registro em AFASTAMENTO. Os colaboradores que não tem nada lançado, nem aparece

    SELECT 
    c.nome AS Colaborador,
    p.projeto AS Projeto,
    d.diasuteis AS DiasUteis,
    d.mes AS MesDiasUteis,
    vr.valor AS Valor,
    SUM(a.dias_refeicao) AS Refeicao,
    MONTH(a.periodo_de) AS Mes,
    ((d.diasuteis - SUM(a.dias_refeicao)) * vr.valor) AS ValorMes
    FROM tb_colaborador c 
    join afastamento a ON a.id_colaborador = c.id_colaborador
    join historico h ON h.id_colaborador = c.id_colaborador
    join projetos p ON p.id_projeto = h.id_projeto
    join diasuteis d ON d.id_projeto = p.id_projeto
    join vr_colaborador vrc ON vrc.id_colaborador = c.id_colaborador
    join vale_refeicao vr ON vr.id_vr = vrc.id_vr
    WHERE 
    MONTH(periodo_de) = 6 
    and 
    h.termino is null
    and
    d.mes = 6
    and 
    vrc.atual = 1
    GROUP BY c.nome, p.projeto, d.diasuteis, vr.valor, d.mes, MONTH(a.periodo_de)


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 12:50

Respostas

  • Bom dia,

    Leonardo, as colunas da tabela relacionada serão nulas se for utilizado o Left Join e não existir uma linha correspondente, então é necessário prever isso nas condições da clausula Where.

    Repare por exemplo que se não existir uma linha na tabela Afastamento para um determinado Colaborador, o valor da coluna a.periodo_de será nulo, então a condição abaixo não será verdadeira:

    MONTH(periodo_de) = 6 

    seria necessário altera-la para algo como segue para que esse colaborador seja retornado:

    (MONTH(periodo_de) = 6 or periodo_de is null)

    Espero que ajude.


    Assinatura: http://www.imoveisemexposicao.com.br

    sexta-feira, 5 de julho de 2013 13:51

Todas as Respostas

  • Leonardo,

    Tente desta forma:

    SELECT 
    c.nome AS Colaborador,
    p.projeto AS Projeto,
    d.diasuteis AS DiasUteis,
    d.mes AS MesDiasUteis,
    vr.valor AS Valor,
    SUM(a.dias_refeicao) AS Refeicao,
    MONTH(a.periodo_de) AS Mes,
    ((d.diasuteis - SUM(a.dias_refeicao)) * vr.valor) AS ValorMes
    FROM tb_colaborador c 
    left join afastamento a ON a.id_colaborador = c.id_colaborador
    left join historico h ON h.id_colaborador = c.id_colaborador
    join projetos p ON p.id_projeto = h.id_projeto
    join diasuteis d ON d.id_projeto = p.id_projeto
    left join vr_colaborador vrc ON vrc.id_colaborador = c.id_colaborador
    left join vale_refeicao vr ON vr.id_vr = vrc.id_vr
    WHERE 
    MONTH(periodo_de) = 6 
    and 
    h.termino is null
    and
    d.mes = 6
    and 
    vrc.atual = 1
    GROUP BY c.nome, p.projeto, d.diasuteis, vr.valor, d.mes, MONTH(a.periodo_de)


    Fabrizzio A. Caputo
    MCT
    Certificações:
    Oracle OCA 11g
    MCITP SQL Server 2008 Implementation and Maintenance
    MCITP SQL Server 2008 Developer
    ITIL V3 Foundation
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Email: fabrizzio.antoniaci@gmail.com


    sexta-feira, 5 de julho de 2013 12:55
    Moderador
  • Deleted
    sexta-feira, 5 de julho de 2013 13:00
  • Pessoal, 

    Continua retornando o mesmo número de linhas que estava retornando anteriormente.

    Obrigado a todos :)


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 13:05
  • Leonardo, o seu problema é que não está sendo retornado as 200 linhas que voce precisa. Correto?

    Só pra eu entender antes de intrometer. rs

    sexta-feira, 5 de julho de 2013 13:09
  • Exatamente Kelvin. 

    Assim, eu tenho 200 colaboradores, para 13 eu lancei afastamento. A query me retorna apenas estes 13, porém, preciso que retorne os 200, e um nulo nos campos de afastamento para quem não tem nada lançado.


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 13:10
  • Saquei.

    Bom cara, pelo que vi a sua query está certa, porem tem um detalhe que normalmente pega a gente.

    Inner Join.

    Esses "join" que voce tem no meio da query devem ser no padrão inner join (isso eu estou deduzindo, me corrija se to falando besteira). Quando a gente usa Inner Join, o registro deve estar nas duas tabelas.

    FROM tb_colaborador c 
    join afastamento a ON a.id_colaborador = c.id_colaborador
    join historico h ON h.id_colaborador = c.id_colaborador
    join projetos p ON p.id_projeto = h.id_projeto
    join diasuteis d ON d.id_projeto = p.id_projeto
    join vr_colaborador vrc ON vrc.id_colaborador = c.id_colaborador
    join vale_refeicao vr ON vr.id_vr = vrc.id_vr

    Nesse seu codigo voce está dizendo que quer retornar SOMENTE os registros que possuem todas essas relações. Uma solução pra resolver isso é colocar todos como Left Join, assim ele vai te retornar os 200 registros.

    Agora pra sua duvida de retornar uma palavra quando o campo for nulo voce pode usar a função COALESCE.

    SELECT CODIGO, COALESCE(NOME_CLIENTE,"Cliente sem nome") AS NOME_CLIENTE
    FROM CLIENTES

    Nesse codigo informo que se a coluna NOME_CLIENTE for nula, irá me retornar "Cliente sem nome" por padrão.

    sexta-feira, 5 de julho de 2013 13:17
  • Então, Kelvin. 

    Após as respostas do pessoal acima, eu fiz usando Left Join, e mesmo assim retornou apenas 13 linhas.


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 13:20
  • Então é hora de testar.

    Voce já tentou tirar alguns campos do select pra ver se retorna os 200?

    por exemplo

    SELECT 
    c.nome AS Colaborador
    
    FROM tb_colaborador c 
    join afastamento a ON a.id_colaborador = c.id_colaborador
    join historico h ON h.id_colaborador = c.id_colaborador
    join projetos p ON p.id_projeto = h.id_projeto
    join diasuteis d ON d.id_projeto = p.id_projeto
    join vr_colaborador vrc ON vrc.id_colaborador = c.id_colaborador
    join vale_refeicao vr ON vr.id_vr = vrc.id_vr
    WHERE 
    MONTH(periodo_de) = 6 
    and 
    h.termino is null
    and
    d.mes = 6
    and 
    vrc.atual = 1
    GROUP BY c.nome, p.projeto, d.diasuteis, vr.valor, d.mes, MONTH(a.periodo_de)
    Pra ver se é um dos campos que estão influenciando

    sexta-feira, 5 de julho de 2013 13:23
  • Algum progresso?
    sexta-feira, 5 de julho de 2013 13:36
  • Nada, cara. 

    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 13:39
  • Continuo restornando 13?

    Voce alterou pra ir com left join?

    SELECT 
    c.nome AS Colaborador
    
    FROM tb_colaborador c 
    left join afastamento a ON a.id_colaborador = c.id_colaborador
    left join  historico h ON h.id_colaborador = c.id_colaborador
    left join  projetos p ON p.id_projeto = h.id_projeto
    left join  diasuteis d ON d.id_projeto = p.id_projeto
    left join  vr_colaborador vrc ON vrc.id_colaborador = c.id_colaborador
    left join  vale_refeicao vr ON vr.id_vr = vrc.id_vr
    WHERE 
    MONTH(periodo_de) = 6 
    and 
    h.termino is null
    and
    d.mes = 6
    and 
    vrc.atual = 1
    GROUP BY c.nome, p.projeto, d.diasuteis, vr.valor, d.mes, MONTH(a.periodo_de)

    Não dando certo, voce pode analisar o que um desses 13 registros tem que os outros não tem, especificamente.

    sexta-feira, 5 de julho de 2013 13:41
  • Bom dia,

    Leonardo, as colunas da tabela relacionada serão nulas se for utilizado o Left Join e não existir uma linha correspondente, então é necessário prever isso nas condições da clausula Where.

    Repare por exemplo que se não existir uma linha na tabela Afastamento para um determinado Colaborador, o valor da coluna a.periodo_de será nulo, então a condição abaixo não será verdadeira:

    MONTH(periodo_de) = 6 

    seria necessário altera-la para algo como segue para que esse colaborador seja retornado:

    (MONTH(periodo_de) = 6 or periodo_de is null)

    Espero que ajude.


    Assinatura: http://www.imoveisemexposicao.com.br

    sexta-feira, 5 de julho de 2013 13:51
  • Já estava com o left join Kelvin. 

    Pelo retorno, está me dando a entender que o problema é a tabela Afastamento mesmo. Pois inseri um afastamento para um colaborador aqui, e passou de 13 para 14 linhas o retorno.


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 13:52
  • E ao inserir um afastamento voce também preenche alguma das outras tabelas que voce usou no SELECT? se for isso provavelmente deve ser o seu Where mesmo, como disse o gabimex, é bom atentar para a sua cláusula WHERE agora.

    Por exemplo o trecho abaixo

    h.termino is null

    se voce tiver 1 funcionario que o afastamento já tenha terminado, ele não será retornado devido a esta cláusula.

    sexta-feira, 5 de julho de 2013 14:04
  • Era exatamente isso o que faltava, gapimex.

    Muito obrigado a todos pela força. Como sempre, continuo aprendendo muita coisa com vocês.

    Obrigado.


    Leonardo D'Amato Microsoft .Net Developer

    sexta-feira, 5 de julho de 2013 14:22