none
Filtro com campo nulo RRS feed

  • Pergunta

  • Bom dia!

    Eu tenho uma procedure assim:

    SELECT     t_ocorrencia.pk_nr_ocorrencia AS [Nº Ocorrência], 
    			t_tecnicos.nm_nome AS Técnico, 
    			CONVERT(varchar(15), t_ocorrencia.dt_data, 103) AS Data, 
                t_instituicao.nm_nome AS Instituição, 
                t_status.nm_status AS Status
    FROM        t_instituicao INNER JOIN t_ocorrencia 
    			ON t_instituicao.pk_cd_instituicao = t_ocorrencia.fk_cd_inst_responsavel 
    			INNER JOIN t_status 
    			ON t_ocorrencia.fk_cd_status = t_status.pk_cd_status 
    			INNER JOIN t_tecnicos 
    			ON t_ocorrencia.fk_cd_tecnico = t_tecnicos.pk_cd_tecnico
    WHERE     
    	(@dt_data_ini IS NULL OR t_ocorrencia.dt_data >= @dt_data_ini)
    AND 
        (@dt_data_fim IS NULL OR t_ocorrencia.dt_data <= @dt_data_fim)
    AND
    	(@fk_status = 0 OR t_ocorrencia.fk_cd_status = @fk_status)
    AND 
    	(@fk_tec = 0 OR t_ocorrencia.fk_cd_tecnico = @fk_tec)
    AND 
    	(@fk_inst = 0 OR t_ocorrencia.fk_cd_inst_responsavel = @fk_inst)
    AND 		
    	(@bl_fauna = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_fauna.fk_nr_ocorrencia FROM t_oco_fauna))  
    AND 		
    	(@bl_flora = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_flora.fk_nr_ocorrencia FROM t_oco_flora))               
    AND 		
    	(@bl_infra = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_infraestrutura.fk_nr_ocorrencia FROM t_oco_infraestrutura))               
    AND 		
    	(@bl_solo = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_relevo_solo.fk_nr_ocorrencia FROM t_oco_relevo_solo))
    ORDER BY t_ocorrencia.dt_data DESC 

    Só que no meu cadastro pode ocorrer de "instituição" ainda não ter sido preechido.

    E nessa consulta só me mostra os cadastros com "instituição" preenchida.

    Alguém tem alguma idéia p/ mostrar todos os cadastros condizentes com o filtro, sendo que se instituição não for selecionada não importa se já tenha sido preenchida ou não, desde que se encaixe, obviamente, nos demais filtros.

    Espero ter conseguido explicar minha dúvida.


    Grata.

    terça-feira, 12 de junho de 2012 12:29

Respostas

  • Olá Cristina,

    veja se o Right Join não te ajuda:

    SELECT     t_ocorrencia.pk_nr_ocorrencia AS [Nº Ocorrência], 
    			t_tecnicos.nm_nome AS Técnico, 
    			CONVERT(varchar(15), t_ocorrencia.dt_data, 103) AS Data, 
                t_instituicao.nm_nome AS Instituição, 
                t_status.nm_status AS Status
    FROM        t_instituicao RIGHT OUTER JOIN t_ocorrencia 
    			ON t_instituicao.pk_cd_instituicao = t_ocorrencia.fk_cd_inst_responsavel 
    			INNER JOIN t_status 
    			ON t_ocorrencia.fk_cd_status = t_status.pk_cd_status 
    			INNER JOIN t_tecnicos 
    			ON t_ocorrencia.fk_cd_tecnico = t_tecnicos.pk_cd_tecnico
    WHERE     
    	(@dt_data_ini IS NULL OR t_ocorrencia.dt_data >= @dt_data_ini)
    AND 
        (@dt_data_fim IS NULL OR t_ocorrencia.dt_data <= @dt_data_fim)
    AND
    	(@fk_status = 0 OR t_ocorrencia.fk_cd_status = @fk_status)
    AND 
    	(@fk_tec = 0 OR t_ocorrencia.fk_cd_tecnico = @fk_tec)
    AND 
    	(@fk_inst = 0 OR t_ocorrencia.fk_cd_inst_responsavel = @fk_inst)
    AND 		
    	(@bl_fauna = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_fauna.fk_nr_ocorrencia FROM t_oco_fauna))  
    AND 		
    	(@bl_flora = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_flora.fk_nr_ocorrencia FROM t_oco_flora))               
    AND 		
    	(@bl_infra = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_infraestrutura.fk_nr_ocorrencia FROM t_oco_infraestrutura))               
    AND 		
    	(@bl_solo = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_relevo_solo.fk_nr_ocorrencia FROM t_oco_relevo_solo))
    ORDER BY t_ocorrencia.dt_data DESC
    Boa Sorte !


    Antero Marques

    terça-feira, 12 de junho de 2012 12:57

Todas as Respostas

  • Eu não sei como está a estrutura do seu banco, mas tenta trocar o primeiro INNER JOIN para LEFT JOIN:

    LEFT JOIN t_ocorrencia 
    ON t_instituicao.pk_cd_instituicao = t_ocorrencia.fk_cd_inst_responsavel 

    DÊ uma olhada nesse artigo: http://www.luis.blog.br/left-join-e-inner-join-juncao-em-consultas-sql.aspx

    Espero ter ajudado, abraços!


    Thiago Coelho
    thiagocoelho.net
    @thiagokoelho

    terça-feira, 12 de junho de 2012 12:49
  • Olá Cristina,

    veja se o Right Join não te ajuda:

    SELECT     t_ocorrencia.pk_nr_ocorrencia AS [Nº Ocorrência], 
    			t_tecnicos.nm_nome AS Técnico, 
    			CONVERT(varchar(15), t_ocorrencia.dt_data, 103) AS Data, 
                t_instituicao.nm_nome AS Instituição, 
                t_status.nm_status AS Status
    FROM        t_instituicao RIGHT OUTER JOIN t_ocorrencia 
    			ON t_instituicao.pk_cd_instituicao = t_ocorrencia.fk_cd_inst_responsavel 
    			INNER JOIN t_status 
    			ON t_ocorrencia.fk_cd_status = t_status.pk_cd_status 
    			INNER JOIN t_tecnicos 
    			ON t_ocorrencia.fk_cd_tecnico = t_tecnicos.pk_cd_tecnico
    WHERE     
    	(@dt_data_ini IS NULL OR t_ocorrencia.dt_data >= @dt_data_ini)
    AND 
        (@dt_data_fim IS NULL OR t_ocorrencia.dt_data <= @dt_data_fim)
    AND
    	(@fk_status = 0 OR t_ocorrencia.fk_cd_status = @fk_status)
    AND 
    	(@fk_tec = 0 OR t_ocorrencia.fk_cd_tecnico = @fk_tec)
    AND 
    	(@fk_inst = 0 OR t_ocorrencia.fk_cd_inst_responsavel = @fk_inst)
    AND 		
    	(@bl_fauna = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_fauna.fk_nr_ocorrencia FROM t_oco_fauna))  
    AND 		
    	(@bl_flora = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_flora.fk_nr_ocorrencia FROM t_oco_flora))               
    AND 		
    	(@bl_infra = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_infraestrutura.fk_nr_ocorrencia FROM t_oco_infraestrutura))               
    AND 		
    	(@bl_solo = 0 OR t_ocorrencia.pk_nr_ocorrencia IN (SELECT t_oco_relevo_solo.fk_nr_ocorrencia FROM t_oco_relevo_solo))
    ORDER BY t_ocorrencia.dt_data DESC
    Boa Sorte !


    Antero Marques

    terça-feira, 12 de junho de 2012 12:57
  • Cristina,

    A sugestão do Antero atende a sua necessidade. Note que a única diferença entre a sugestão do Antero e do Thiago é o uso do LEFT ou RIGHT JOIN. Eles são muito parecidos, apenas que eles determinam qual dos "lados" deve ser retornado todos os registros, tendo ou não associação (JOIN) com a outra tabela. Neste caso, da forma como está construida a sua query, o RIGHT é mais aplicável, pois evitará que você tenha que mexer na sua query para trocar os lados das tabelas t_instituicao e t_ocorrencia para utilizar o LEFT.

    Por uma questão de padronização, eu evito ao máximo misturar RIGHT com LEFT nas minhas queries, porque fica mais fácil no momento de uma manutenção, mas, note, isso é somente uma sugestão quando você construir mais e mais queries....

    Eu tomaria um certo cuidado com as suas subqueries, para não ter dor de cabeça no futuro com baixa performance. Imaginando que a sua query mais externa retorne apenas um registro, pela sua construção, o SQL terá que acessar os dados no mínimo 5 vezes, seja em memória ou em disco, uma para a query externa, e 1 vez para cada um das subqueries (t_oco_fauna, t_oco_flora, t_oco_infraestrutura e t_oco_relevo_solo). Note que, isso não é um problema, mas é bom avaliar para que nao se torne no futuro. Imagine que esta query possa ser executada milhares de vezes por dia.

    Espero ter ajudado.


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008

    quarta-feira, 13 de junho de 2012 00:20
    Moderador