【问题标题】:Sql Server - Comparing time only in 24 hour format?Sql Server - 仅以 24 小时格式比较时间?
【发布时间】:2017-02-03 17:54:00
【问题描述】:

我想将时间与时间范围进行比较,如果该特定时间在该时间范围内,那么它应该返回一条记录。

例如,表“A”有:

+-----------+------+-------------+-----------+
| User_Code | Name | Shift_Start | Shift_End |
+-----------+------+-------------+-----------+
|         1 | ABC  | 04:01:00    | 11:00:00  |
|         2 | DEF  | 11:01:00    | 20:00:00  |
|         3 | XYZ  | 20:01:00    | 04:00:00  |
+-----------+------+-------------+-----------+

现在我想检查在这个特定日期时间是谁的班次:2016-09-26 02:51:59。 SQL 查询应返回User_Code = 3。 Shift_Start 和 Shift_End 的类型为 time。

我尝试将2016-09-26 02:51:59 转换为时间,然后使用between 和logical operator 与shift_start 和shift_end 进行比较,但我无法获得所需的结果。

这让我很困惑。自从我尝试提出解决方案以来已经一个小时了,但我无法这样做。尝试使用谷歌搜索,但那里也一无所获。任何帮助将不胜感激。使用 SQL Server 2012。

【问题讨论】:

  • 如果您只想处理TIME 而不是DATETIME,将20:01:00 - 04:00:00 XYZ 范围分成两个范围可能会让您的生活更轻松:00:00:00 - 04:00:00 XYZ 和20:01:00 - 23:59:59 XYZ跨度>
  • @paul,是的,但我真的不想改变数据库结构,但我同意这会让事情变得更容易。

标签: sql sql-server


【解决方案1】:

您需要更复杂的where 条件,因为班次时间可以是任意顺序。

所以:

where ((shift_start < shift_end) and
       cast(@datetime as time) between shift_start and shift_end)
      ) or
      ((shift_start > shift_end) and
       cast(@datetime as time) not between shift_end and shift_start)
      )

【讨论】:

  • 谢谢兄弟。我没有意识到我也可以“不介于”。
  • @Gordon Linoff,我知道这已经得到解答。但是当我尝试通过 @datetime = '2016-09-24 17:51:59' 时,它给出了 2 行(2&3)而不是 1 行。
  • @user3583912 。 . . between 和 not between 的运算符需要首先具有较低的值。
【解决方案2】:
declare @t table(
    User_Code int,
    Name varchar(20),
    Shift_Start time,
    Shift_End time
    );
insert @t(User_Code,Name,Shift_Start,Shift_End)
values
 (1,'ABC','04:01:00','11:00:00')
,(2,'DEF','11:01:00','20:00:00')
,(3,'XYZ','20:01:00','04:00:00');

试试

declare @d datetime = '2016-09-26 02:51:59';

select *
from @t
cross apply ( -- intermediate vars: rounded param 
         select dt = cast(cast(@d as date) as datetime)
            ) r
where @d between dateadd(d, case when Shift_Start<Shift_End then 0 else -1 end, dt) + cast(Shift_start as datetime)  
         and dt+cast(Shift_end as datetime);

【讨论】:

    【解决方案3】:

    从另一个角度接近并将搜索条件的日期部分添加到班次开始和结束时间:

    注意 case 语句,它处理了班次结束跨越午夜的情况。

     DECLARE @dateTime DATETIME = '2016-09-26 02:51:59'
     -- Remove the time portion of above
     DECLARE @datePortion DATETIME = DATEADD(dd, 0, DATEDIFF(dd, 0, @dateTime)) 
    
     SELECT * FROM TableA 
       WHERE @dateTime BETWEEN @datePortion + cast(Shift_Start as datetime)
                        AND CASE WHEN ShiftEnd < ShiftStart
                               THEN DATEADD(day, 1, @datePortion)
                               ELSE @datePortion
                            END + cast(Shift_End as datetime)
    

    【讨论】:

    • 很遗憾,这并没有产生预期的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多