none
Filtro en tipo de dato Time RRS feed

  • Pregunta

  • Buenas noches,

    Deseo consultar a la tabla que contiene hora y esta estan dentro de ella según a la fecha actual. Para controlar las horas que se queda en la cochera.

    Caso HoraInicio Horafinal   Monto

    1      06:00        20:00        5.00

    2      20:00       06:00         7.00

    Para el primer caso me funcion: Siendo GETDATE() en hora de la mañana por ejemplo las 10:20

    SELECT HoraInicio, HoraFinal, Monto FROM Control 
    WHERE CONVERT(TIME(0), GETDATE()) BETWEEN HoraInicio AND HoraFinal
    El resultado es 1 registro

    pero para el segundo caso ya no me funciona, como puedo hacer para el filtro.

    Siendo GETDATE() en hora de la noche por ejemplo 22:10

    Gracis de antemano por su respuesta


    Si se puede imaginar... se puede programar. Me encanta depender de la tecnología para vengarme de ella y dominarla como los locos.

    sábado, 5 de diciembre de 2020 2:23

Todas las respuestas

  • Hola SysEdw:

    Esta podría ser una solución:

    Declare @Tabla Table
    					 (
    					 caso       Int
    				   , horainicio Time(0)
    				   , horafinal  Time(0)
    				   , monto      Decimal(3, 2)
    					 );
    
    Insert Into @Tabla(caso
    				 , horainicio
    				 , horafinal
    				 , monto)
    Values
    	   ( 1, '06:00', '20:00', 5.00 ),
    	   ( 2, '20:00', '06:00', 7.00 );
    
    Declare @Fechasimulada DateTime = '20201205 22:10';
    
    Select *
    	   From @Tabla As t
    	   Where t.horainicio < Convert(Time(0), @Fechasimulada) 
    	   And (
    			(t.horafinal > Convert(Time(0), @Fechasimulada) 
    			Or t.horafinal < t.horainicio)
    			);

    Si la hora final es menor que la hora a buscar o si es menor que la hora inicial (por tanto ya sería del día siguiente)

    sábado, 5 de diciembre de 2020 6:18
  • Hola Javi;

    He probado tu scrip;

    pero al cambiar la fecha simulada a la fecha actual, no realiza la busqueda

    Declare @Fechasimulada DateTime = '20201205 01:40'


    Si se puede imaginar... se puede programar. Me encanta depender de la tecnología para vengarme de ella y dominarla como los locos.

    sábado, 5 de diciembre de 2020 6:49
  • Hola SysEdw:

    Declare @Tabla Table
    					 (
    					 caso       Int
    				   , horainicio Time(0)
    				   , horafinal  Time(0)
    				   , monto      Decimal(3, 2)
    					 );
    
    Insert Into @Tabla(caso
    				 , horainicio
    				 , horafinal
    				 , monto)
    Values
    	   ( 1, '06:00', '20:00', 5.00 ),
    	   ( 2, '20:00', '06:00', 7.00 );
    
    Declare @Fechasimulada DateTime = Getdate()
    Select @fechaSimulada;
    Select *
    	   From @Tabla As t
    	   Where t.horainicio < Convert(Time(0), @Fechasimulada) 
    	   And (
    			(t.horafinal > Convert(Time(0), @Fechasimulada) 
    			Or t.horafinal < t.horainicio)
    			);

    Aquí son las 09:18

    ¿Que filas debería de traerte?

    sábado, 5 de diciembre de 2020 8:20
  • Ok ya lo he entendido, cuando el margen sea por debajo.
    sábado, 5 de diciembre de 2020 8:21
  • Asi tienes cubiertos los tres casos

    Declare @Tabla Table
    					 (
    					 caso       Int
    				   , horainicio Time(0)
    				   , horafinal  Time(0)
    				   , monto      Decimal(3, 2)
    					 );
    
    Insert Into @Tabla(caso
    				 , horainicio
    				 , horafinal
    				 , monto)
    Values
    	   ( 1, '06:00', '19:00', 5.00 ),
    	   ( 2, '20:00', '04:00', 7.00 );
    Declare @Fechasimulada DateTime = '20200101 01:40'
    
    
    Select *
    	   From @Tabla As t
    	   Where 
    	   -- caso 1 la hora esta entre el inicio y el final.
    	   (
    		t.horainicio < Convert(Time(0), @Fechasimulada)
    		and 
    		t.horafinal > Convert(Time(0), @Fechasimulada)
    	   ) 
    	   or 
    	   -- Caso 2 la hora de inicio es mayor
    	   ( t.horainicio > Convert(Time(0), @Fechasimulada)
    		and 
    		-- Pero también es mayor que la hora final
    		t.horainicio > t.horafinal
    		and
    		-- pero la hora final es mayor que la hora
    		   t.horafinal > Convert(Time(0), @Fechasimulada) 
    	   )
    	   or
    	   -- Caso 3 
    	   ( t.horainicio < Convert(Time(0), @Fechasimulada)
    		and 
    	    t.horafinal < t.horainicio
    		)
    

    Fíjate que te he puesto un rango diferente en la entrada para que puedas evaluar cualquier causística.

    Espero te ayude

    sábado, 5 de diciembre de 2020 8:36
  • Gracias, con esto si me ayuda bastante


    Si se puede imaginar... se puede programar. Me encanta depender de la tecnología para vengarme de ella y dominarla como los locos.

    sábado, 5 de diciembre de 2020 8:42
  • Es quizá mucho más bonito utilizar una función para esto:

    Create function dbo.isTimeRange (@startTime time(0), @endTime time(0), @DateTime dateTime)
    Returns bit
    Begin
    	return (
    		Select case when 
    		(
    			@startTime < Convert(Time(0), @DateTime)
    			and 
    			@endTime > Convert(Time(0), @DateTime)
    		) 
    	   Or 
    	   -- Caso 2 la hora de inicio es mayor
    	   ( 
    			@startTime > Convert(Time(0), @DateTime)
    			and 
    			-- Pero también es mayor que la hora final
    			@startTime > @endTime
    			and
    			-- pero la hora final es mayor que la hora
    			@endTime > Convert(Time(0), @DateTime) 
    	   )
    	   Or
    	   -- Caso 3 
    	   ( 
    			@startTime < Convert(Time(0), @DateTime)
    			and 
    			@endTime < @startTime
    	   )
    	   then 1 
    	   else 0 
    	   end as isRange
    		)
    End;

    Encapsulas el código que vas a aplicar como restricción en una función que evalúa si esta en el rango.

    Y luego la llamas, tal que;

    Declare @Tabla Table
    					 (
    					 caso       Int
    				   , horainicio Time(0)
    				   , horafinal  Time(0)
    				   , monto      Decimal(3, 2)
    					 );
    
    Insert Into @Tabla(caso
    				 , horainicio
    				 , horafinal
    				 , monto)
    Values
    	   ( 1, '06:00', '19:00', 5.00 ),
    	   ( 2, '20:00', '04:00', 7.00 );
    
    Declare @fechaSimulada datetime= getdate();
    
    Select *
    	   From @Tabla As t
    	   Where 
    	   dbo.isTimeRange(t.horainicio, t.horafinal, @fechasimulada)=1;
    Si vas a utilizar millones de filas con esta idea, entonces, ya tendrías que pensar en utilizar una función tipo tabla en vez de una función escalar, quizá un cross apply, u otras opciones un poco más complejas.

    sábado, 5 de diciembre de 2020 9:21