2012-06-11 16 views
5

Quindi quello che sto cercando è generare tutte le ore che si trovano all'interno di un intervallo di tempo specifico.Ottieni ogni ora per un intervallo di tempo

Quindi, dato il campo 11:00-14:00, otterrei:

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

sto cercando di evitare di dover memorizzare ogni ora specifica un negozio potrebbe essere aperto e solo memorizzare l'intervallo (I bisogno di confrontare le ore contro altre volte)

Grazie

+2

Memorizzare semplicemente 'OpenTime' e' ClosedTime' nel db e fare i confronti nel codice?!?! –

+0

Quale versione di SQL Server? – Lamak

+0

@Lamak: 2008 r2 – Limey

risposta

5

Se si dispone di un numbers table (clicca sul link per crearne uno se non) ...

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) 

Se questo è specializzato, puoi creare una tabella delle ore con solo 24 valori.

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 È leggermente diverso. La mia risposta originale diceva anche di creare la tabella delle ore come opzione, ma non ho incluso un esempio per mostrare come avrebbe funzionato. Mi scuso se sembra che abbia rubato il tuo suggerimento. – Zhenny

+0

Siamo spiacenti. Sembrava che tu avessi creato una risposta, poi dopo aver visto la mia risposta, hai cambiato idea e anche la mia risposta. Chiedo scusa. –

4

Il modo più semplice che posso pensare di farlo è quello di avere solo 1 tavolo permanente con un elenco di tutte le ore; 24 voci in totale.

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

Poi, dato i tempi A & B:

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

Mi piace questa idea, darò uno scatto. – Limey

+0

'= <' and '=>'? –

+0

So cosa vogliono dire; hai provato la sintassi che hai effettivamente postato? 'IF 1 = <2 PRINT 'um';' restituisce 'Msg 102, Level 15, State 1, Line 1 Sintassi errata vicino a '<'.' –

7

È possibile utilizzare un CTE ricorsivo. Questo genera le ore tra le 11 e 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

Mi piace il meglio, ma restituisce un int e non un tempo, ma sono sicuro che posso modificare per lavorare con un tempo – Limey

+0

@AaronBertrand: sì, intendevo int e tempo, ho modificato il mio commento. – Limey

11

Nessun loop, CTE ricorsive o numeri tabella richiesta.

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

Mi sento sempre viscido usando le tabelle sys in questo modo. Sembra un po 'hackerato. – Zhenny

+1

@Zhenny Bene, preferisco personalmente una tabella 'Numbers', ma finché non ne viene fornita una sola con SQL Server, prova a convincere tutti a crearne una. [Si prega di votare e commentare, forse ne otterremo uno nella prossima versione] (http://connect.microsoft.com/SQLServer/feedback/details/258733/add-a-built-in-table-of-numbers) ! –

+1

C'è un modo in cui questa soluzione potrebbe essere modificata per tenere conto di un cambio di giorno? Ad esempio se volessi ogni ora tra le 23:00 del lunedì alle 2 del martedì –

0

@Andomar Grazie mille, mi hai aiutato, c'è il mio add sopra il tuo codice.

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

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) 
----------------------------* 
Problemi correlati