2012-06-11 7 views
5

Więc próbuję wygenerować wszystkie godziny, które są w określonym zakresie czasu.Otrzymuj co godzinę w zakresie czasu

Więc biorąc pod uwagę zakres 11 rano do 2:00 po południu, chciałbym uzyskać:

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

próbuję uniknąć konieczności przechowywania każdą konkretną godzinę sklep może być otwarty i po prostu zapisać zakres (I trzeba porównać godzin przed innymi razy)

Dzięki

+2

Po prostu przechowuj '' OpenTime' i 'ClosedTime' w bazie danych i wykonuj porównania w kodzie?!?! –

+0

Jaką wersję programu SQL Server? – Lamak

+0

@Lamak: 2008 r2 – Limey

Odpowiedz

5

Jeśli masz numbers table (kliknij w link, aby utworzyć jedną, jeśli nie) ...

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) 

Jeśli jest to wyspecjalizowane, możesz utworzyć tabelę godzin z tylko 24 wartościami.

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 To trochę inaczej. Moja oryginalna odpowiedź również powiedziała, że ​​mogę utworzyć tabelę godzin jako opcję, ale nie podałem przykładu, aby pokazać, jak to by działało. Przepraszam, jeśli wydaje mi się, że ukradłem twoją sugestię. – Zhenny

+0

Przepraszamy. Wyglądało na to, że stworzyłeś odpowiedź, a po zobaczeniu mojej odpowiedzi zmieniłeś zdanie i udzieliłeś mojej odpowiedzi. Przepraszam. –

4

najłatwiej można myślę, aby to zrobić, aby mieć tylko 1 stały tabelę z listą wszystkich godzin; Łącznie 24 wpisy.

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

Następnie podane razy & B:

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

Podoba mi się ten pomysł, dam temu szansę. – Limey

+0

'= <' and '=>'? –

+0

Wiem, co mają na myśli; czy wypróbowałeś składnię, którą opublikowałeś? 'IF 1 = <2 PRINT 'um';' daje 'Msg 102, Level 15, State 1, Line 1 Niepoprawna składnia w pobliżu '<'.' –

7

Można użyć rekurencyjnego CTE. To generuje godzin pomiędzy 11 i 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

Podoba mi się to, co najlepsze, ale zwraca int i nie czas, ale jestem pewien, że mogę modyfikować do pracy z czasem – Limey

+0

@AaronBertrand: tak, miałem na myśli int i czas, zredagowałem mój komentarz. – Limey

11

Nie pętle cyklicznych CTE lub liczby wymaganych tabeli.

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

Zawsze czuję się obślizgły przy użyciu tabel Sys w ten sposób. Czuje się trochę hackish. – Zhenny

+1

@Zhenny Cóż, wolę osobiście tabelę 'Numbers', ale dopóki nie zostanie dostarczona z serwerem SQL, spróbuj przekonać wszystkich, aby ją utworzyli. [Głosuj i komentuj, może dostaniemy jeden w następnej wersji] (http://connect.microsoft.com/SQLServer/feedback/details/258733/add-a-built-in-table-of-numbers) ! –

+1

Czy istnieje sposób, w jaki to rozwiązanie można zmodyfikować, aby uwzględnić zmianę dnia? Na przykład, jeśli chcesz mieć każdą godzinę między 23:00 od poniedziałku do 2 nad ranem we wtorek –

0

@Andomar Wielkie dzięki, pomogłeś mi, jest mój dodatek powyżej kodu.

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

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) 
----------------------------* 
Powiązane problemy