none
Sentencia SQL con un If RRS feed

  • Pregunta

  • Buen día.

    Estoy trabajando en un Procedimiento Almacenado, el cual tiene la función de buscar unos datos por un rango de fechas y otras variables. Estas otras variables son opciones, solo el rango de fechas es obligatoria.

    Entonces tengo un Select sencillo:

    select *

    from tabla1 inner join tabla2 on tabla1.codigo = tabla2.codTabla1

    where tabla1.fecha between '20180112 00:00:00' and '20180112 23:59:59'

    Lo que necesito saber es si yo puedo agregar un If o algo que me permita agregarle otra sentencia al Where si la variable tiene datos o no, por ejemplo:

    select *

    from tabla1 inner join tabla2 on tabla1.codigo = tabla2.codTabla1

    where tabla1.fecha between '20180112 00:00:00' and '20180112 23:59:59'

    if (@variable = '') Begin

    and tabla1.Anulado = 'N'

    end

    else begin

    and tabla1.Anulado = 'S'

    end

    Espero haberme dado a entender y de antemano gracias por la ayuda que me puedan dar.

     

    viernes, 12 de enero de 2018 15:30

Respuestas

  • Es posible realizar la validación que mencionas con algunos cambios de sintaxis en la expresión:

    SELECT *
    FROM 
        tabla1
        INNER JOIN tabla2 ON tabla1.codigo = tabla2.codTabla1
    WHERE 
        tabla1.fecha BETWEEN '20180112 00:00:00' AND '20180112 23:59:59'
        AND ((tabla1.Anulado = 'N' AND @variable = '') OR (tabla1.Anulado = 'S' AND @variable <> ''));
    GO

    viernes, 12 de enero de 2018 15:41
  • Esa es una alternativa fácil de programar pero considero que es algo peligrosa a la hora del rendimiento ya que si esto se hace más complejo que dos o tres alternativas de condiciones opcionales suele suceder que el planificador termina eligiendo planes ineficientes cuando hay muchas condiciones OR y termina haciendo un TABLE SCAN. 


    Yo sugiero usar IF

    IF @condicion is not null
    BEGIN
       --consulta completa con @condicion agregada
    END
    ELSE
    BEGIN
       -- Consulta completa sin @condicion agregada
    END


    Es mucho más trabajoso pero conozco a alguien que se tomó el trabajo de armar un programita que generaba todas las  2^N combinaciones (N son las condicioenes opcionales). Lo hizo mediante un árbol binario y recursión.

    Otra alternativa es usar código dinámico que solo tiene un pequeño costo adicional de CPU en la compilación que para el caso habitual de los reportes no es significativo (si fuera algo que se ejecuta millones de veces es mucho mejor el IF) y permite al planificador usar un plan más adecuado.

    Saludos



    Ing. Jose Mariano Alvarez - http://blog.josemarianoalvarez.com

    viernes, 12 de enero de 2018 16:19
  • Hola, podrias utilizar un case en el where,algo como

    create table #pruebas
    (
     id int identity(1,1),
     nombre varchar(100),
     fecha  datetime,
     anulado   char(1)
     )
    
     insert into #pruebas (nombre,fecha,anulado) values ('eduardo', getdate(),'s')
     insert into #pruebas (nombre,fecha,anulado) values ('jose', getdate(),'s')
     insert into #pruebas (nombre,fecha,anulado) values ('luis', getdate(),'n')
    
       declare @VARIABLE as varchar(10)
       set @VARIABLE=''
       select * from #pruebas
       where anulado= case @VARIABLE when '' then 's' else 'n' end
       set @VARIABLE='algo'
       select * from #pruebas
       where anulado= case @VARIABLE when '' then 's' else 'n' end
       drop table #pruebas

    select *
    from tabla1 inner join tabla2 on tabla1.codigo = tabla2.codTabla1
    where tabla1.fecha between '20180112 00:00:00' and '20180112 23:59:59'
    and tabla1.Anulado= case @VARIABLE when '' then 'N' else 'S' end


    Votar es agradecer.
    Saludos.
    Lima-Perú




    viernes, 12 de enero de 2018 15:42

Todas las respuestas

  • Es posible realizar la validación que mencionas con algunos cambios de sintaxis en la expresión:

    SELECT *
    FROM 
        tabla1
        INNER JOIN tabla2 ON tabla1.codigo = tabla2.codTabla1
    WHERE 
        tabla1.fecha BETWEEN '20180112 00:00:00' AND '20180112 23:59:59'
        AND ((tabla1.Anulado = 'N' AND @variable = '') OR (tabla1.Anulado = 'S' AND @variable <> ''));
    GO

    viernes, 12 de enero de 2018 15:41
  • Hola, podrias utilizar un case en el where,algo como

    create table #pruebas
    (
     id int identity(1,1),
     nombre varchar(100),
     fecha  datetime,
     anulado   char(1)
     )
    
     insert into #pruebas (nombre,fecha,anulado) values ('eduardo', getdate(),'s')
     insert into #pruebas (nombre,fecha,anulado) values ('jose', getdate(),'s')
     insert into #pruebas (nombre,fecha,anulado) values ('luis', getdate(),'n')
    
       declare @VARIABLE as varchar(10)
       set @VARIABLE=''
       select * from #pruebas
       where anulado= case @VARIABLE when '' then 's' else 'n' end
       set @VARIABLE='algo'
       select * from #pruebas
       where anulado= case @VARIABLE when '' then 's' else 'n' end
       drop table #pruebas

    select *
    from tabla1 inner join tabla2 on tabla1.codigo = tabla2.codTabla1
    where tabla1.fecha between '20180112 00:00:00' and '20180112 23:59:59'
    and tabla1.Anulado= case @VARIABLE when '' then 'N' else 'S' end


    Votar es agradecer.
    Saludos.
    Lima-Perú




    viernes, 12 de enero de 2018 15:42
  • Gracias!!
    viernes, 12 de enero de 2018 16:15
  • Gracias!!
    viernes, 12 de enero de 2018 16:16
  • Esa es una alternativa fácil de programar pero considero que es algo peligrosa a la hora del rendimiento ya que si esto se hace más complejo que dos o tres alternativas de condiciones opcionales suele suceder que el planificador termina eligiendo planes ineficientes cuando hay muchas condiciones OR y termina haciendo un TABLE SCAN. 


    Yo sugiero usar IF

    IF @condicion is not null
    BEGIN
       --consulta completa con @condicion agregada
    END
    ELSE
    BEGIN
       -- Consulta completa sin @condicion agregada
    END


    Es mucho más trabajoso pero conozco a alguien que se tomó el trabajo de armar un programita que generaba todas las  2^N combinaciones (N son las condicioenes opcionales). Lo hizo mediante un árbol binario y recursión.

    Otra alternativa es usar código dinámico que solo tiene un pequeño costo adicional de CPU en la compilación que para el caso habitual de los reportes no es significativo (si fuera algo que se ejecuta millones de veces es mucho mejor el IF) y permite al planificador usar un plan más adecuado.

    Saludos



    Ing. Jose Mariano Alvarez - http://blog.josemarianoalvarez.com

    viernes, 12 de enero de 2018 16:19