【问题标题】:Get every hour for a time range获取一个时间范围内的每小时
【发布时间】:2012-06-11 19:30:52
【问题描述】:

所以我想要生成特定时间范围内的所有时间。

所以考虑到上午 11 点到下午 2:00 的范围,我会得到:

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

我试图避免存储商店可能开放的每个特定时间,只存储范围(我需要将时间与其他时间进行比较)

谢谢

【问题讨论】:

  • 只需将OpenTimeClosedTime 存储在数据库中,然后在代码中进行比较?!?!

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

不需要循环、递归 CTE 或数字表。

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;

【讨论】:

  • 我总是觉得用这种方式使用 sys 表很糊。感觉有点hackish。
  • @Zhenny 好吧,我个人更喜欢Numbers 表,但在 SQL Server 附带一张表之前,请尝试说服每个人创建一张表。 Please vote and comment, maybe we'll get one in the next version!
  • 有没有办法修改这个解决方案来解决一天的变化?例如,如果您希望在星期一晚上 11 点到星期二凌晨 2 点之间的每一个小时
【解决方案2】:

您可以使用递归 CTE。这将生成 11 到 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.

【讨论】:

  • 我最喜欢它,但它返回一个 int 而不是时间,但我确信我可以修改为使用时间
  • @AaronBertrand:是的,我的意思是整数和时间,我编辑了我的评论。
【解决方案3】:

如果您有numbers table(如果没有,请单击链接创建一个)...

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)

如果这是专门的,您可以创建一个只有 24 个值的小时表。

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

【讨论】:

  • @David 略有不同。我最初的回答还说创建小时表作为一个选项,但我没有包括一个例子来说明它是如何工作的。抱歉,如果我似乎偷了你的建议。
  • 对不起。看起来你创造了你的答案,然后在看到我的答案后,你改变了主意,也把我的答案放了出来。我很抱歉。
【解决方案4】:

我能想到的最简单的方法是只有一张永久表,其中包含所有时间的列表;共 24 个条目。

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

然后,给定时间 A 和 B:

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

【讨论】:

  • 我喜欢这个主意,我会试一试。
  • 我知道他们的意思;您是否尝试过实际发布的语法? IF 1=&lt;2 PRINT 'um'; 产生 Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '&lt;'.
  • @DavidManheim 请非常接近查看您发布的代码。 =&lt; &lt;=!相同
  • 哎呀!谢谢你的收获。 (已修复。我删除了以前的 cmets。)
【解决方案5】:

@Andomar 非常感谢,你帮助了我,我在你的代码上方添加了。

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

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

【讨论】:

    猜你喜欢
    • 2022-12-03
    • 2012-10-21
    • 2011-06-28
    • 1970-01-01
    • 2021-08-17
    • 2020-10-09
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    相关资源
    最近更新 更多