2012-06-11 7 views
5

Entonces, lo que estoy tratando de generar todas las horas que están dentro de un rango de tiempo específico.Obtenga cada hora para un rango de tiempo

Así que da un tamaño de 11 am a 2:00 pm, me gustaría tener:

11:00 AM 
12:00 PM 
1:00 PM 
2:00 PM 

que estoy tratando de evitar tener que almacenar cada hora específica de una tienda podría ser abierto y simplemente almacenar el rango (I necesidad de comparar las horas contra otras veces)

Gracias

+2

Simplemente almacene el 'OpenTime' y el' ClosedTime' en el db, y haga sus comparaciones en el código?!?! –

+0

¿Qué versión de SQL Server? – Lamak

+0

@Lamak: 2008 r2 – Limey

Respuesta

5

Si usted tiene un numbers table (haga clic en el enlace para crear uno si no lo hace) ...

create table test(
    startTime time 
, endTime time 
) 

insert into test 
select '11:00', '14:00' 

select 
    dateadd(hh, n.n, t.startTime) as times 
from test t 
    inner join Numbers n 
    -- assuming your numbers start at 1 rather than 0 
    on n.n-1 <= datediff(hh, t.startTime, t.endTime) 

Si esto es especializado, puede crear una tabla de horas con solo 24 valores.

create table HoursInADay(
    [hours] time not null 
, constraint PK_HoursInADay primary key ([hours]) 
) 

-- insert 
insert into HoursInADay select '1:00' 
insert into HoursInADay select '2:00' 
insert into HoursInADay select '3:00' 
insert into HoursInADay select '4:00' 
insert into HoursInADay select '5:00' 
insert into HoursInADay select '6:00' 
insert into HoursInADay select '7:00' 
... 

select 
    h.[hours] 
from test t 
    inner join HoursInADay h 
    on h.[hours] between t.startTime and t.endTime 
+1

@David Es ligeramente diferente. Mi respuesta original también decía que creara la tabla de horas como una opción, pero no incluí un ejemplo para mostrar cómo funcionaría. Disculpas si parece que robé tu sugerencia. – Zhenny

+0

Lo siento. Parecía que creaste tu respuesta, luego, después de ver mi respuesta, cambiaste de opinión y también respondiste. Me disculpo. –

4

La forma más sencilla que puedo pensar para hacer esto es tener sólo el 1 tabla permanente con una lista de todas las horas; 24 entradas en total.

Create table dbo.Hours (Hourly_Time Time NOT NULL) 
Insert into dbo.Hours ... 

Entonces, tiempos dados Un & B:

select * from dbo.Hours where Hourly_Time<=A and Hourly_Time>=B 
+1

Me gusta esta idea, daré una oportunidad. – Limey

+0

'= <' and '=>'? –

+0

Sé lo que significan; ¿Intentó la sintaxis que publicó? 'IF 1 = <2 PRINT 'um';' produce 'Msg 102, nivel 15, estado 1, línea 1 Sintaxis incorrecta cerca de '<'.' –

7

Puede utilizar un CTE recursivo. Esto generaría las horas entre las 11 y 14:

;with Hours as 
     (
     select 11 as hr 
     union all 
     select hr + 1 
     from Hours 
     where hr < 14 
     ) 
select * 
from Hours 

Live example at SQL Fiddle.

+0

Me gusta el mejor, pero devuelve un int y no un tiempo, pero estoy seguro de que puedo modificar para trabajar con un tiempo – Limey

+0

@ AaronBertrand: sí, quise decir int y el tiempo, edité mi comentario. – Limey

11

No hay bucles, CTE recursivas o números de tabla requerida.

DECLARE 
    @start TIME(0) = '11:00 AM', 
    @end TIME(0) = '2:00 PM'; 

WITH x(n) AS 
(
    SELECT TOP (DATEDIFF(HOUR, @start, @end) + 1) 
    rn = ROW_NUMBER() OVER (ORDER BY [object_id]) 
    FROM sys.all_columns ORDER BY [object_id] 
) 
SELECT t = DATEADD(HOUR, n-1, @start) FROM x ORDER BY t; 
+2

Siempre me siento fangoso usando las tablas de sys de esta manera. Se siente un poco hackish. – Zhenny

+1

@Zhenny Bueno, prefiero una tabla 'Numbers' personalmente, pero hasta que se envíe con SQL Server, intente convencer a todos para que creen una. [Por favor, vote y comente, tal vez obtengamos uno en la próxima versión] (http://connect.microsoft.com/SQLServer/feedback/details/258733/add-a-built-in-table-of-numbers) ! –

+1

¿Hay alguna manera de modificar esta solución para dar cuenta de un cambio de día? Por ejemplo, si quisiera cada hora entre las 11:00 p.m. del lunes a las 2 a.m. del martes –

0

@Andomar Muchas gracias, me han ayudado, hay mi complemento encima de su código.

*---------------------------- 

create view vw_hoursalot as 
    with Hours as 
    (
     select DATEADD(
     dd, 0, DATEDIFF(
       dd, 0, DATEADD (
        year , -5 , getDate() 
       ) 
      ) 
    ) as dtHr 
    union all 
     select DATEADD (minute , 30 , dtHr) 
     from Hours 
     where dtHr < DATEADD(
      dd, 0, DATEDIFF(
        dd, 0, DATEADD (
         year , +5 , getDate() 
        ) 
       ) 
     ) 
) 
    select * from Hours 
---------------------------- 
select * from vw_hoursalot option (maxrecursion 0) 
----------------------------* 
Cuestiones relacionadas