2017-04-21 39 views
0

我需要查找自上次班次开始以来已更改的记录。 换班时间从07:00开始(上午),15:00(下午)和23:00(夜间)开始。SQL Server找到最近的班次开始(时间)到一个日期

例如。现在是17点15分,所以我正在下午轮班。现在我想查找自上次班次开始以来已更改的工作相关记录。所以我需要前一天15:00的开始时间。那是24小时前+当前班次的时间。

我需要一个可以作为where子句的一部分实现的解决方案。

基本上我尝试找到一个班次的最后一个开始(7,15或23h),然后从该日期开始减去另一个24小时。并让查询运行到当前时间。

select * from workorder 
where changedate >= getDate() - 24h - time_in_shift 

select * from workorder 
where changedate >= last_shift_start - 24h 

说实话,我还没有找到一个很好的策略呢。起初,我试图用case语句找到正确的转换,并用它来做正确的计算。但我认为这不是最好的办法。

select getDate() as now, 
case 
    when datepart(hh, getDate())-23 >= 0 then 'night' 
    when datepart(hh, getDate())-15 >= 0 then 'afternoon' 
    when datepart(hh, getDate())-7 >= 0 then 'morning' 
    else 'night' 
end as shift; 

下面是一些样本数据

id changedate 
1 '2017-04-20 01:00:00' 
2 '2017-04-20 02:00:00' 
3 '2017-04-20 08:00:00' 
4 '2017-04-20 09:00:00' 
5 '2017-04-20 14:00:00' 
6 '2017-04-20 16:00:00' 
7 '2017-04-20 17:00:00' 
8 '2017-04-20 22:00:00' 
9 '2017-04-20 23:00:00' 
10 '2017-04-20 23:30:00' 
11 '2017-04-21 01:10:00' 
12 '2017-04-21 02:10:00' 
13 '2017-04-21 08:10:00' 
14 '2017-04-21 10:10:00' 
15 '2017-04-21 16:10:00' 
16 '2017-04-21 16:20:00' 

可以说,现在是2017年4月21日17:00:00。所以我正在下午换班。 这意味着我想要记录自我上次开始以来已更改的所有记录。因此从2017-04-20 15:00:00开始。除了前5个以外,都是所有记录。

+2

请张贴一些样本数据和预期的输出。 –

+0

您是否计划对换档开始时间进行硬编码并回顾24小时? –

+0

是的,它是一个可配置的结果查询,所以很容易访问和不太可能改变 – Jeroen

回答

1

如果您使用SQL Server 2012中,你可以用一个case语句建立你WHERE条款:

select * 
from workorder 
where changedate >= case 
      when datepart(hh, getDate()) >= 23 
       then smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
              month(dateadd(day, -1, cast(getdate() as date))), 
              day(dateadd(day, -1, cast(getdate() as date))), 
              23, 00) 
      when datepart(hh, getDate()) < 7 
       then smalldatetimefromparts(year(dateadd(day, -2, cast(getdate() as date))), 
              month(dateadd(day, -2, cast(getdate() as date))), 
              day(dateadd(day, -2, cast(getdate() as date))), 
              23, 00) 
      when datepart(hh, getDate()) between 15 and 22 
       then smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
              month(dateadd(day, -1, cast(getdate() as date))), 
              day(dateadd(day, -1, cast(getdate() as date))), 
              15, 00) 
      else smalldatetimefromparts(year(dateadd(day, -1, cast(getdate() as date))), 
             month(dateadd(day, -1, cast(getdate() as date))), 
             day(dateadd(day, -1, cast(getdate() as date))), 
             7, 00) 
     end; 

如果你使用旧版本的SQL Server,可以通过几次明确的转换来替代smalldatetimefromparts;你可以看到它解释this answer

+0

建立一个日期时间与'getDate() - 1'在一个月的第一个失败。 –

+0

你是对的,谢谢。我修好了它 –

1

第一件事是一个换班表(只有一列)。当然你可以立即生成这个,但为什么不在你的数据库中?

 
shiftstart 
07:00 
15:00 
23:00 

为了得到当前的转变,你可以做这样的事情:

select 
    coaleasce 
    (
    max(case when shiftstart < cast(getdate() as time) then shiftstart end), 
    max(shiftstart) 
) 
from shift; 

添加昨天以获取昨日shiftstart:

dateadd(day, -1, cast(getdate() as date)) + <above time> 

UPDATE:正如Damien_The_Unbeliever正确指出的那样:

,如果它是目前02:00,我们想要的一切后,两个23:00日前

因此,我们必须减去取决于时间或者一两天。


完整的调整查询:

select * 
from workorder 
where changedate >= 
(
    select 
    coaleasce 
    (
     dateadd(day, -1, cast(getdate() as date)) + 
     max(case when shiftstart < cast(getdate() as time) then shiftstart end), 
     dateadd(day, -2, cast(getdate() as date)) + 
     max(shiftstart) 
    ) 
    from shift 
); 
相关问题