none
necesito ayuda con el where gracias RRS feed

  • Pregunta

  • ALTER procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    if(@tipo = 1)
    fecharrecepcion is null
    if(@tipo = 2)
    fecharcontestar is null
    if(@tipo = 3)
    fecharcontestar is null
    if(@tipo = 4)
    nro = @buscar
    if(@tipo = 5)
    emisor = @buscar

    pero me sale un error como puede hacer un condicionate para el where gracias por sus respuestas

    miércoles, 11 de abril de 2018 5:14

Respuestas

  • Hola Israel:

    A lo mejor estas buscando algo así.

    	DECLARE @TIPO INT = 1
    		DECLARE @BUSCAR VARCHAR(50) = '1'
    		SELECT TOP 30 R.CODIGO, R.NRDOC,CASE WHEN @TIPO = 1 THEN NULL ELSE R.FECHARECEPCION END AS FECHARECEPCION
    					 , R.EMISOR, R.ASUNTO, R.FOLIO, CASE WHEN @TIPO BETWEEN 2 AND 3 THEN NULL ELSE  R.FECHACONTESTAR END AS FECHACONTESTAR,
    					  R.RESPUESTA
    			
    		
    		
    		FROM RECEPCIONDOCUMENTOS R INNER JOIN TIPO_RECEPCIONDOCUMENTOS T ON R.TIPORECEPCION = T.CODIGO
    		WHERE
    			CASE WHEN @TIPO BETWEEN 1 AND 3 THEN @TIPO
    			WHEN @TIPO BETWEEN 4 AND 5 THEN
    				CAST (@BUSCAR AS int)
    			 END = T.CODIGO

    Fijate que entiendo que las columnas devuelven un valor en funcion del tipo. Ojo el tipo es int, no varchar 1 como lo has definido en el procedimiento. Si tu tabla es varchar 1, se compara con '1'.

    Luego el where, entiendo que si el tipo es 1, 2 o 3, busca por el tipado de tiporecepcion, pero si es 4 o 5 entonces busca el nrdoc. Dado que en mi tabla, eso es int, lo casteo porque el procedure recibe un varchar.

    Espero te sirva.

    Saludos

    miércoles, 11 de abril de 2018 5:57
  • Desde el punto de vista de rendimiento y porque los planes de ejecución que se generan serían distintos yo haría lo siguiente

    ALTER procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    if(@tipo = 1)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharrecepcion is null
    if(@tipo = 2)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharcontestar is null
    if(@tipo = 3)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharcontestar is null
    if(@tipo = 4)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    nro = @buscar
    if(@tipo = 5)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    emisor = @buscar

    Es muchísimo mas largo, pero igual de simple, pero se te generarán varios planes de ejecución específicos para cada tipo de búsqueda por lo que me inclino a pensar que desde el punto de vista de rendimiento será mucho mejor


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 11 de abril de 2018 7:31
    Moderador
  • ALTER procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    if(@tipo = 1)
    fecharrecepcion is null
    if(@tipo = 2)
    fecharcontestar is null
    if(@tipo = 3)
    fecharcontestar is null
    if(@tipo = 4)
    nro = @buscar
    if(@tipo = 5)
    emisor = @buscar

    pero me sale un error como puede hacer un condicionate para el where gracias por sus respuestas

    miércoles, 11 de abril de 2018 5:11
  • Hola Israel:

    En prinicipio la sentencia para evaluar en una select, es case

    Bajo su consulta, podría ser como así

    case when nivelcontrol =1 then 1 end = @tipo

    Pero realmente, no lo tiene planteado correctamente.

    Que quiere obtener, todos los registros de sus dos tablas, si tipo = 1 por ejemplo que tengan una fecharecepcion nula.

    https://technet.microsoft.com/es-es/library/ms189074(v=sql.105).aspx

    Indique por favor el sentido de su consulta, porque no parece claro.

    El case se puede usar tambien en las columnas.

    case when F.fecharecepcion is null then '01/01/2000' else fecharecepcion END as [FechaRECEPCION]
    Un saludo

    miércoles, 11 de abril de 2018 5:29
  • Una sintaxis para las columnas puede ser tal que así:

    SELECT CASE WHEN NIVELCONTROL = 1 THEN /*evaluo un resultado */
    				CASE WHEN ESTADO=0 THEN 'ACTIVO' /*dentro de esta evaluacion realizo otra */
    					ELSE 'BAJA'  /* si no se cumple ESTADO = 0 ENTONCES */
    					END /*FINALIZA EL CASE PARA LAS OPCIONES DE NIVELCONTROL = 1 */
    			WHEN NIVELCONTROL =12 THEN /* SEGUNDA EVALUACION DEL CASE */
    					'ACTIVADOPOR2' 
    			END  /* FIN DEL CASE */
    		AS ESTADOS /*ALIAS DE COLUMNA */
    
    	FROM FACTURACION
    		

    Un saludo

    miércoles, 11 de abril de 2018 5:38
  • Entiendo tu punto, pero considera lo siguiente

    1 cambio te llevará a ti 3-4 minutos de tu tiempo en cambiar 4-5 selects, además es prácticamente copiar y pegar más probar que funciona.

    Si solamente fuese 3 segundos mas rápido y lo ejecutan mil usuarios 20 días, el tiempo total que invierte tu empresa en ese punto es mucho menor en el que gastas tu, que en el que pierden los usuarios esperando tu sistema.

    Si quieres evitar hacerlo varias veces te diría que dentro del procedimiento llames a sp_executesql, 

    tu primera parte del procedimiento crearía toda la sentencia menos el where en una variable,

    no lo he probado, porque no tengo tus tablas y porque el objetivo es que lo resuelvas por tus medios, pero aquí te pego la idea

    create procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    declare @sql nvarchar(2000)='select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    '
    if(@tipo = 1)
    begin
     set @sql=@sql+' where fecharrecepcion is null'
     exec sp_executesql @sql,''
    end
    
    if(@tipo = 2)
    begin 
     set @sql=@sql+' where fecharcontestar is null '
     exec sp_executesql @sql,''
    end
    if(@tipo = 3)
    begin 
     set @sql=@sql+' where fecharcontestar is null '
     exec sp_executesql @sql,''
    end
    
    if(@tipo = 4)
    begin 
     set @sql=@sql+' where nro = @buscar'
     exec sp_executesql @sql,'@buscar varchar(50)',@buscar
    end
    
    if(@tipo = 5)
    begin 
     set @sql=@sql+' where emisor = @buscar'
     exec sp_executesql @sql,'@buscar varchar(50)',@buscar
    end
    Esta aproximación no tiene problemas de inyección de código al usar sp_execute sql de la forma adecuada, pero si es ejecución dinámica, aunque según la parametrización de tu server probablemente se creen los planes de ejecución separados por cada una de las ejecuciones (si no los considera triviales) y se reaprovechen. Es decir, no creo que pierdas gran cosa en términos de rendimiento


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA


    jueves, 12 de abril de 2018 6:17
    Moderador

Todas las respuestas

  • ALTER procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    if(@tipo = 1)
    fecharrecepcion is null
    if(@tipo = 2)
    fecharcontestar is null
    if(@tipo = 3)
    fecharcontestar is null
    if(@tipo = 4)
    nro = @buscar
    if(@tipo = 5)
    emisor = @buscar

    pero me sale un error como puede hacer un condicionate para el where gracias por sus respuestas

    miércoles, 11 de abril de 2018 5:11
  • Hola Israel:

    En prinicipio la sentencia para evaluar en una select, es case

    Bajo su consulta, podría ser como así

    case when nivelcontrol =1 then 1 end = @tipo

    Pero realmente, no lo tiene planteado correctamente.

    Que quiere obtener, todos los registros de sus dos tablas, si tipo = 1 por ejemplo que tengan una fecharecepcion nula.

    https://technet.microsoft.com/es-es/library/ms189074(v=sql.105).aspx

    Indique por favor el sentido de su consulta, porque no parece claro.

    El case se puede usar tambien en las columnas.

    case when F.fecharecepcion is null then '01/01/2000' else fecharecepcion END as [FechaRECEPCION]
    Un saludo

    miércoles, 11 de abril de 2018 5:29
  • Una sintaxis para las columnas puede ser tal que así:

    SELECT CASE WHEN NIVELCONTROL = 1 THEN /*evaluo un resultado */
    				CASE WHEN ESTADO=0 THEN 'ACTIVO' /*dentro de esta evaluacion realizo otra */
    					ELSE 'BAJA'  /* si no se cumple ESTADO = 0 ENTONCES */
    					END /*FINALIZA EL CASE PARA LAS OPCIONES DE NIVELCONTROL = 1 */
    			WHEN NIVELCONTROL =12 THEN /* SEGUNDA EVALUACION DEL CASE */
    					'ACTIVADOPOR2' 
    			END  /* FIN DEL CASE */
    		AS ESTADOS /*ALIAS DE COLUMNA */
    
    	FROM FACTURACION
    		

    Un saludo

    miércoles, 11 de abril de 2018 5:38
  • Hola Israel:

    A lo mejor estas buscando algo así.

    	DECLARE @TIPO INT = 1
    		DECLARE @BUSCAR VARCHAR(50) = '1'
    		SELECT TOP 30 R.CODIGO, R.NRDOC,CASE WHEN @TIPO = 1 THEN NULL ELSE R.FECHARECEPCION END AS FECHARECEPCION
    					 , R.EMISOR, R.ASUNTO, R.FOLIO, CASE WHEN @TIPO BETWEEN 2 AND 3 THEN NULL ELSE  R.FECHACONTESTAR END AS FECHACONTESTAR,
    					  R.RESPUESTA
    			
    		
    		
    		FROM RECEPCIONDOCUMENTOS R INNER JOIN TIPO_RECEPCIONDOCUMENTOS T ON R.TIPORECEPCION = T.CODIGO
    		WHERE
    			CASE WHEN @TIPO BETWEEN 1 AND 3 THEN @TIPO
    			WHEN @TIPO BETWEEN 4 AND 5 THEN
    				CAST (@BUSCAR AS int)
    			 END = T.CODIGO

    Fijate que entiendo que las columnas devuelven un valor en funcion del tipo. Ojo el tipo es int, no varchar 1 como lo has definido en el procedimiento. Si tu tabla es varchar 1, se compara con '1'.

    Luego el where, entiendo que si el tipo es 1, 2 o 3, busca por el tipado de tiporecepcion, pero si es 4 o 5 entonces busca el nrdoc. Dado que en mi tabla, eso es int, lo casteo porque el procedure recibe un varchar.

    Espero te sirva.

    Saludos

    miércoles, 11 de abril de 2018 5:57
  • Desde el punto de vista de rendimiento y porque los planes de ejecución que se generan serían distintos yo haría lo siguiente

    ALTER procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    if(@tipo = 1)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharrecepcion is null
    if(@tipo = 2)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharcontestar is null
    if(@tipo = 3)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    fecharcontestar is null
    if(@tipo = 4)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    nro = @buscar
    if(@tipo = 5)
    select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    where 
    emisor = @buscar

    Es muchísimo mas largo, pero igual de simple, pero se te generarán varios planes de ejecución específicos para cada tipo de búsqueda por lo que me inclino a pensar que desde el punto de vista de rendimiento será mucho mejor


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    miércoles, 11 de abril de 2018 7:31
    Moderador
  • Dando te las gracias por responder pero en el caso del entero no hay problema y si me equivoque pero es asunto es que, si desde el programa yo presiono la tecla 1 debe solo soltar todos los datos, si presiono los datos del 2 debe salir solo los datos que faltan si presiono el 3 me debe filtar solo por fechas no recibidas y el filtar por nro de expediente, y el 5 filtar por alguna parte del texto inscrito, he encontrado una solucion pero es muy larga muchas gracias por la ayuda
    jueves, 12 de abril de 2018 4:23
  • si muchas gracias en si eso fue lo primero que hice, y esta funcionando, pero lo que queria era si el condicionate sea en where porque si tengo que hacer algun cxambio en el select tendria que cambiar el todos los if, siendo lo mas facil que solo haya un select y solo el condicionante del where gracias de todas maneras por la ayuda 
    jueves, 12 de abril de 2018 4:25
  • Gracias por la ayuda estoy tratando de implantarlo la solucion gracias
    jueves, 12 de abril de 2018 4:28
  • Entiendo tu punto, pero considera lo siguiente

    1 cambio te llevará a ti 3-4 minutos de tu tiempo en cambiar 4-5 selects, además es prácticamente copiar y pegar más probar que funciona.

    Si solamente fuese 3 segundos mas rápido y lo ejecutan mil usuarios 20 días, el tiempo total que invierte tu empresa en ese punto es mucho menor en el que gastas tu, que en el que pierden los usuarios esperando tu sistema.

    Si quieres evitar hacerlo varias veces te diría que dentro del procedimiento llames a sp_executesql, 

    tu primera parte del procedimiento crearía toda la sentencia menos el where en una variable,

    no lo he probado, porque no tengo tus tablas y porque el objetivo es que lo resuelvas por tus medios, pero aquí te pego la idea

    create procedure [dbo].[sp_recepciondocumentos_ver] 
    @tipo varchar(1),
    @buscar varchar(50)
    as
    declare @sql nvarchar(2000)='select 
    TOP 30
    recepciondocumentos.codigo as [Codigo],
    tipo_recepciondocumentos.descripcion as [Descripcion],
    nrodoc as [Numero],
    fecharecepcion as [Fecha],
    emisor as [Emisor],
    asunto as [Asunto],
    folio as [Folio],
    fechacontestar as [Contestado],
    respuesta as [respuesta]
    from dbo.recepciondocumentos 
    INNER JOIN dbo.tipo_recepciondocumentos ON recepciondocumentos.tiporecepcion = tipo_recepciondocumentos.codigo
    '
    if(@tipo = 1)
    begin
     set @sql=@sql+' where fecharrecepcion is null'
     exec sp_executesql @sql,''
    end
    
    if(@tipo = 2)
    begin 
     set @sql=@sql+' where fecharcontestar is null '
     exec sp_executesql @sql,''
    end
    if(@tipo = 3)
    begin 
     set @sql=@sql+' where fecharcontestar is null '
     exec sp_executesql @sql,''
    end
    
    if(@tipo = 4)
    begin 
     set @sql=@sql+' where nro = @buscar'
     exec sp_executesql @sql,'@buscar varchar(50)',@buscar
    end
    
    if(@tipo = 5)
    begin 
     set @sql=@sql+' where emisor = @buscar'
     exec sp_executesql @sql,'@buscar varchar(50)',@buscar
    end
    Esta aproximación no tiene problemas de inyección de código al usar sp_execute sql de la forma adecuada, pero si es ejecución dinámica, aunque según la parametrización de tu server probablemente se creen los planes de ejecución separados por cada una de las ejecuciones (si no los considera triviales) y se reaprovechen. Es decir, no creo que pierdas gran cosa en términos de rendimiento


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA


    jueves, 12 de abril de 2018 6:17
    Moderador
  • Es deseable que no abras mas de un hilo con el mismo asunto.

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    jueves, 12 de abril de 2018 6:19
    Moderador