SQL Server查找最近的班次开始(时间)到日期

时间:2017-04-21 13:50:24

标签: sql sql-server tsql date datetime

我需要查找自上次班次开始以来已更改的记录。 班次从早上7点(早上),下午15点(下午)和晚上23点(晚上)开始。

例如。现在是17:15h,所以我在下午班。现在我想找到自上次班次开始以来已经改变的工作相关记录。所以我需要前一天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-04-21 17:00:00。所以我今天下午轮班。 这意味着我想要自从我之前开始以来已经改变的所有记录。因此从2017-04-20 15:00:00开始。这是除前5个以外的所有记录。

2 个答案:

答案 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;

昨天添加以获得昨天的班次开始:

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

更新:正如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
);

答案 1 :(得分:1)

如果您正在使用SQL Server 2012,则可以使用案例声明构建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

中看到它的解释