我有引擎开始工作的日期时间以及工作时间。但有时它可以工作超过24小时。
如果在开始日期工作28小时,我将有记录
Name started_working Finished working hours_worked
obj-00123 07/02/2018 13:30 08/02/2018 17:30 28
我需要有记录显示发动机在07年10:30和08年17:30工作。
Name started_working Finished working hours_worked
obj-00123 07/02/2018 13:30 07/02/2018 00:00 10:30
obj-00123 07/02/2018 13:30 08/02/2018 17:30 17:30
或类似的东西。我不知道如何才能完成这项工作。你能给我一些线索吗?如果不太容易,我不会要求编写代码。
谢谢
答案 0 :(得分:1)
这可能会为你做到这一点
--Using CTE to show sample data
;WITH cteX( Name,started_working,Finished_working)
AS
(
SELECT
'obj-00123','07/02/2018 13:30','08/02/2018 17:30' UNION ALL
SELECT 'obj-00155','07/02/2018 15:00','07/02/2018 22:30'
)
SELECT
X.Name
, X.started_working
, X.Finished_working
, HoursWorked = CONVERT(VARCHAR(12), DATEADD(minute, DATEDIFF(minute, X.started_working, X.Finished_working), 0), 114)
FROM
(
SELECT
T1.Name
,T1.started_working
,Finished_working = DATEADD(SECOND,0,DATEADD(DAY, DATEDIFF(DAY,-1,T1.started_working),0)) -- Dummy finish time @ Midnight
FROM
cteX T1
WHERE
DATEDIFF(DAY,T1.started_working,T1.Finished_working) <> 0 --Create a dummy finish time @Midnight when start and end not on same day
UNION ALL
SELECT
T2.Name
,started_working = CASE WHEN DATEDIFF(DAY,T2.started_working,T2.Finished_working) <> 0
THEN DATEADD(DAY, DATEDIFF(DAY, 0, T2.Finished_working), 0) --Start @ Midnight
ELSE T2.started_working
END
,T2.Finished_working
FROM
cteX T2
) X
ORDER BY
X.Name, X.started_working
输出
Name started_working Finished_working HoursWorked
obj-00123 2018-07-02 13:30:00.000 2018-07-03 00:00:00.000 10:30:00:000
obj-00123 2018-08-02 00:00:00.000 2018-08-02 17:30:00.000 17:30:00:000
obj-00155 2018-07-02 15:00:00.000 2018-07-02 22:30:00.000 07:30:00:000
答案 1 :(得分:0)
我会接近这样的解决方案:
WITH dynamic_twelths_of_hr_table(datetime2_value) AS
(
SELECT '2017-01-01'
UNION ALL
SELECT DATEADD(MINUTE, 5, datetime2_value)
FROM dynamic_twelths_of_hr_table
WHERE DATEADD(MINUTE, 5, datetime2_value) <= '2019-01-01'
)
,twelths_hr_table AS
(
SELECT
DATEADD(DAY, DATEDIFF(DAY, 0, datetime2_value), 0) AS date_value
,datetime2_value
FROM dynamic_twelths_of_hr_table
)
,modified_source_table AS
(
SELECT
name
,objectid
,engine_start
,ISNULL(engine_stop, GETDATE()) AS engine_stop
,IIF(engine_start IS NULL OR engine_stop IS NULL, 1, 0) AS is_still_running
FROM [YOUR_SOURCE_TABLE]
)
SELECT
name
,objectid
,is_still_running
,date_value
,(COUNT(datetime2_value)/12.0) AS hours_run_on_this_day
FROM
modified_source_table
LEFT JOIN
twelths_hr_table AS tht
ON (tht.datetime2_value BETWEEN engine_start AND engine_stop)
GROUP BY
name, objectid, is_still_running, date_value
ORDER BY
name, objectid, is_still_running, date_value
注意我还没有测试过这段代码,所以请原谅任何小的语法错误。
我还假设要考虑的日期范围(这些可以扩大,或根据查询运行时的动态变化),并且它有5分钟的分辨率(基于这样的事实,乍一看,我只能在engine_stop
列中看到一个没有落在5分钟阈值上的值 - 所以我假设不需要5分钟以下的精度。
它的作用基本上是将每个引擎行扩展到5分钟的窗口(每小时的十二分之一),然后简单地按日分组,并计算引擎运行期间每天的窗口数。
对于当前正在运行的引擎,它将计算到目前为止运行的时间。我相信您可以根据您的具体要求调整代码。
答案 2 :(得分:0)
根据您的样本数据,工作时间可能超过几天。在这种情况下,您需要使用计数表或递归CTE。我使用了递归CTE,因为它更容易处理结果字段。此外,结果中有两列名为started_working
和started_working2
。 started_working
来自您的预期输出,但我认为您需要started_working2
列
declare @T as table (
Name varchar(100)
, started_working datetime
, finished_working datetime
--, hours_worked int
)
insert into @T
values
('obj-00123', '20180207 13:30', '20180208 17:30')
, ('obj-00123', '20180208 19:00', '20180209 05:00')
, ('obj-00123', '20180209 19:00', '20180209 22:00')
, ('obj-00123', '20180210 19:00', '20180213 22:00')
;with rcte as (
select
*, started_working2 = started_working
, next_date = cast(dateadd(dd, 1, started_working) as date), 1 step
from
@T
union all
select
Name, started_working, finished_working
, cast(next_date as datetime)
, dateadd(dd, 1, next_date), step + 1
from
rcte
where
next_date < finished_working
)
select
Name, started_working, started_working2, finished_working
, right(replace(str(diff / 60), ' ', 0), 2) + ':' + right(replace(str(diff % 60), ' ', 0), 2) hours_worked
from (
select
Name, started_working
, case
when step = 1 then started_working
else started_working2
end started_working2
, case
when step = max(step) over (partition by Name, started_working)
then finished_working else next_date
end finished_working
from
rcte
) t
cross apply (select datediff(mi, started_working2, finished_working) diff) ca
答案 3 :(得分:0)
但创建视图是CTE的一个问题。
创建视图mroobjectenginerowkinghoursdeclare as 将@T声明为表格( 名称nvarchar(100) ,OBJECTID varchar(50) ,started_working datetime ,STOPFROM日期时间 ,开始日期时间 ,STOPDATE datetime ,MODIFIEDDATETIME日期时间 ,START_STOP int ,STARTDESCRIPTION nvarchar(300) ,STOPDESCRIPTION nvarchar(300) ,瓦数nvarchar(50) ,用途nvarchar(300) ,地点nvarchar(300) ,finished_working日期时间 ,oldDiff int )
插入@T 选择 名称 ,OBJECTID ,停下来 ,STOPFROM ,开始日期 ,STOPDATE ,MODIFIEDDATETIME ,START_STOP ,STARTDESCRIPTION ,STOPDESCRIPTION ,瓦数 ,目的 ,地点 ,next_stopfrom ,DIFF 来自[MicrosoftDynamicsAX]。[dbo]。[mroobjectengineworkinghours]
;以rcte为( 选择 *,started_working2 = started_working ,next_date = cast(dateadd(dd,1,started_working)as date),1步 从 @T 联合所有 选择 名称,OBJECTID,started_working,STOPFROM,STARTDATE,STOPDATE,MODIFIEDDATETIME,START_STOP,STARTDESCRIPTION ,STOPDESCRIPTION,瓦数 ,目的 ,location,finished_working,oldDiff ,cast(next_date as datetime) ,dateadd(dd,1,next_date),步骤+ 1 从 rcte 哪里 next_date&lt; finished_working )
选择 名称,OBJECTID,started_working,STOPFROM,STARTDATE,STOPDATE,MODIFIEDDATETIME,START_STOP,STARTDESCRIPTION ,STOPDESCRIPTION,瓦数 ,目的 ,location,oldDiff,started_working2,finished_working ,右(替换(str(差异/ 60),&#39;&#39;,0),2)+&#39;:&#39; +右(替换(str(diff%60),&#39;&#39;,0),2)hours_worked 来自( 选择 名称,OBJECTID,started_working,STOPFROM,STARTDATE,STOPDATE,MODIFIEDDATETIME,START_STOP,STARTDESCRIPTION ,STOPDESCRIPTION,瓦数 ,目的 ,位置,oldDiff , 案件 当step = 1然后start_working 否则started_working2 结束started_working2 , 案件 当step = max(step)over(按名称分区,started_working) 然后finished_working else next_date 结束完成工作 从 rcte )t 交叉申请(选择datediff(mi,started_working2,finished_working)diff)ca 选项(MAXRECURSION 0);