【问题标题】:Seperate time intervals by workday按工作日分隔时间间隔
【发布时间】:2016-12-12 21:12:36
【问题描述】:

我有下表(但有更多数据):

Workcenter ID | Status | Start Date/Time | End Date/Time SLX83D Breakdown 11/27/2016 16:00:00 11/29/2016 12:30:00 SLX83C No Operator 11/27/2016 6:40:00 11/27/2016 13:00:00 SLX83A QA Inspection 11/28/2016 13:00:00 11/28/2016 14:00:00 SLX83A QA Inspection 11/28/2016 15:00:00 11/28/2016 16:00:00

我想按工作日(即 12/1 6am 到 12/2 6am)分隔状态时间间隔并求和。

我的想法是按以下格式创建交叉表查询:

Work Day | Workcenter ID | Breakdown | No Operator | QA Inspection 11/27/2016 SLX83D 14:00:00 11/28/2016 SLX83D 24:00:00 11/29/2016 SLX83D 6:30:00 11/27/2016 SLX83C 6:20:00 11/28/2016 SLX83A 2:00:00

不知道如何让它发挥作用,我对其他想法持开放态度。

附: 我的表中还有以下列:开始日期、开始时间、结束日期和结束时间。 (这些用于计算“开始日期/时间”和“结束日期/时间”

我对 Access 比较陌生,对 SQL 几乎一无所知,谢谢。

编辑: 通过在我的表中创建以下计算列,我能够找到给定日期的状态:

介于日期之间: IIf([Start Date/Time]>= "11/28/2016 06:00:00" And [End Date/Time]<= "11/29/2016 06:00:00" ,[End Date/Time]-[Start Date/Time],0)*24*60

在日期之前开始: IIf([Start Date/Time]< "11/28/2016 06:00:00" And [End Date/Time]>= "11/28/2016 06:00:00" And [End Date/Time]<= "11/29/2016 06:00:00" ,[End Date/Time]- "11/28/2016 06:00:00" ,0)*24*60

在日期之后结束: IIf([End Date/Time]> "11/28/2016 06:00:00" And [Start Date/Time]>= "11/28/2016 06:00:00" And [Start Date/Time]<= "11/29/2016 06:00:00" , "11/29/2016 06:00:00" -[Start Date/Time],0)*24*60

跨越整个日期: IIf([Start Date/Time]< "11/28/2016 06:00:00" And [End Date/Time]> "11/29/2016 06:00:00" ,1,0)*24*60

将这些列相加得出给定工作中心在给定日期具有给定状态的总分钟数。
但是,这一次仅适用于一个工作日日期。我更愿意弄清楚如何使用 SQL 来获得如上表所示的工作日历史结果。

Workcenter ID | Status | Start Date/Time | End Date/Time SLX83D Breakdown 11/27/2016 16:00:00 11/29/2016 12:30:00 SLX83A QA Inspection 11/28/2016 13:00:00 11/28/2016 14:00:00 SLX83A QA Inspection 11/28/2016 15:00:00 11/28/2016 16:00:00

Workcenter ID | IBD | SBD | EAD | SWD | SUM SLX83D 1440 1440 (24 hrs) SLX83A 60 60 (1 hr) SLX83A 60 60 (These 2 hrs would have to be summed later somehow, this isn't a great solution)

编辑 2: 我尝试了以下方法,但无法正常工作。 (信用转至:https://social.msdn.microsoft.com/Forums/sqlserver/en-US/cca28ddd-2041-4504-b602-3bedd9ca704e/counts-by-time-interval?forum=transactsql#208e97ad-11a7-4d96-9436-c82612755d46

SELECT DatePart(Day,[Start Date/Time]) AS [Workday Date], Count([Status Table].[Workcenter ID]) AS [Workday Interval]

FROM [Status Table]

WHERE ((([Status Table].[Start Date/Time]) Between [Start Date/Time] And [End Date/Time]))

GROUP BY DatePart(Day,interval);

【问题讨论】:

  • 您的示例数据的期望结果是什么?
  • @Parfait,我想知道工作中心在给定工作日处于给定状态的总时间(即 SLX83D 的状态跨越 3 个工作日并将被拆分。SLX83A 有一个工作日内两次相同的状态,因此它们被加在一起)。这有助于澄清吗?

标签: sql ms-access


【解决方案1】:

考虑分多个阶段处理您的需求:

  1. 为所有可能的工作日开始(第一天早上 6:00)和结束点(第二天早上 5:59)构建一个时间表表。如果天数达到数百或数千,这可能需要使用 VBA 循环从最早到最晚的日期动态创建一个新表 (TableDef)。

  2. 结合所有三个可能的持续时间的联合查询: a) 部分天开始; b) 多个全天; c) 部分日终。每个都使用嵌套的IIF() 逻辑来计算小时数。每个SELECT 查询都将使用Actual Hours 表和Schedule 表运行交叉连接和间隔过滤器。

  3. 跨选项卡查询以在按 WorkDatesID 分组的转换输出中进行聚合,并按 Status 列进行透视。

联合查询 (一定要去掉cmets,不符合Access SQL查询语句)。

-- ACTUAL START PARTIAL
SELECT w.[Workcenter ID], w.Status, w.[StartDate/Time], w.[End Date/Time], 
       s.WorkStartDates, s.WorkEndDates,
       IIF(w.[StartDate/Time] >= s.WorkStartDates AND w.[End Date/Time] <= s.WorkEndDates,
         DateDiff('n', w.[StartDate/Time], w.[End Date/Time]), 
         IIF(w.[StartDate/Time] >= s.WorkStartDates AND w.[End Date/Time] >= s.WorkEndDates,
             DateDiff('n', w.[StartDate/Time], s.WorkEndDates), NULL)) / 60 AS WorkHours
FROM WorkCenterHours w, Schedule s
WHERE w.[StartDate/Time] BETWEEN s.WorkStartDates AND s.WorkEndDates

UNION

-- ACTUAL START AND END ACROSS WORKDAYS
SELECT w.[Workcenter ID], w.Status, w.[StartDate/Time], w.[End Date/Time], 
       s.WorkStartDates, s.WorkEndDates,
       DateDiff('n', s.WorkStartDates, s.WorkEndDates) / 60 As WorkHours
FROM WorkCenterHours w, Schedule s
WHERE s.WorkStartDates BETWEEN w.[StartDate/Time] AND w.[End Date/Time]
AND s.WorkEndDates BETWEEN w.[StartDate/Time] AND w.[End Date/Time]

UNION 

-- ACTUAL END LEFTOVER
SELECT w.[Workcenter ID], w.Status, w.[StartDate/Time], w.[End Date/Time],
       s.WorkStartDates, s.WorkEndDates,
       IIF(w.[StartDate/Time] <= s.WorkStartDates AND w.[End Date/Time] <= s.WorkEndDates,
         DateDiff('n', w.[End Date/Time], s.WorkEndDates), 
         IIF(w.[StartDate/Time] >= s.WorkStartDates AND w.[End Date/Time] <= s.WorkEndDates,
             DateDiff('n', w.[StartDate/Time], w.[End Date/Time]), NULL)) / 60 AS WorkHours
FROM WorkCenterHours w, Schedule s
WHERE w.[End Date/Time] BETWEEN s.WorkStartDates AND s.WorkEndDates;

跨标签查询 (使用上面作为数据源)

TRANSFORM Sum(q.WorkHours) AS SumOfWorkHours
SELECT DateValue(q.WorkStartDates) AS WorkDate, q.[Workcenter ID]
FROM UnionSourceQuery q
GROUP BY DateValue(q.WorkStartDates), q.[Workcenter ID]
PIVOT q.Status;

注意:由于联合查询中的交叉连接过滤器使用嵌套逻辑和各种日期函数调用,因此无法保证性能,并且可能会因数据大小而异,最终会被透视。

【讨论】:

  • 我刚刚将联合查询中最后一行的第 5 行更改为:DateDiff('n', s.WorkStartDates, w.[End Date/Time] ), 看起来对吗?我认为它现在运行良好。
  • 好收获!确实应该改成这样!只要确保你在关注 =) ...很高兴我能帮上忙。
  • 太棒了,很棒的解决方案!现在有动力学习 SQL :)
猜你喜欢
  • 1970-01-01
  • 2016-10-06
  • 2018-09-24
  • 2011-12-20
  • 2015-03-01
  • 1970-01-01
  • 2011-02-08
  • 2019-06-28
  • 2018-10-12
相关资源
最近更新 更多