我需要查找自上次班次开始以来已更改的记录。 班次从早上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个以外的所有记录。
答案 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