我正在尝试在我们的生产线上创建可视化。我们有两条线路,有几百人,每个都有不同的人员轮班策略。通过循环记录,我已经能够在Access中生成我想要的结果。 我想将其升级到SQL Server并提高速度。
有人可以指出我正确的方向吗?
以下是适用于Access的VBA代码。
Public Function MakeLaborData()
Dim db As dao.Database
Dim rs As dao.Recordset
Dim hr As Date
Dim LaborOn As Date
Dim LaborOff As Date
Dim Hours As Double
Set db = CurrentDb
Set rs1 = db.OpenRecordset("t_Labor") 'myTable is a MS-Access table created previously
Set rs2 = db.OpenRecordset("t_Labor_by_Hour")
Do While Not rs1.EOF
LaborOn = rs1.Fields("LABOR_ON").Value
If IsNull(rs1.Fields("LABOR_OFF").Value) Then
LaborOff = Now()
Else
LaborOff = rs1.Fields("LABOR_OFF").Value
End If
hr = DateSerial(DatePart("yyyy", LaborOn), DatePart("m", LaborOn), DatePart("d", LaborOn)) + (DatePart("h", LaborOn) / 24)
Do Until hr > LaborOff
If LaborOn > hr And LaborOff < hr + 1 / 24 Then
Hours = (LaborOff - LaborOn) * 24
ElseIf LaborOn > hr And LaborOff > hr + 1 / 24 Then
Hours = ((hr + 1 / 24) - LaborOn) * 24
ElseIf LaborOn < hr And LaborOff > hr + 1 / 24 Then
Hours = 1
ElseIf LaborOn < hr And LaborOff < hr + 1 / 24 Then
Hours = (LaborOff - hr) * 24
Else
Hours = 0
End If
With rs2
.AddNew
!Line_Number = rs1!UNIT
!SOI = rs1!JOB
!Employee = rs1!Employee
!Hour_of_Day = hr
!Labor_Hours = Hours
.Update
End With
hr = hr + 1 / 24
Loop
rs1.MoveNext
Loop
rs1.Close
rs2.Close
End Function
答案 0 :(得分:2)
我建议一个表格,其中包含每个班次(工作期间)的开始和停止时间,因此如果Bob工作1.75小时,那么Bob将在早上6:30开始并在8点停止:上午15点。您需要在三个工作小时内显示此信息是一个演示问题,而不是数据问题。您可以在上午12点到中午12点之间每小时都有一个“小时”表。如果您使用此新表加入Hour表,则会获得3个结果。
答案 1 :(得分:2)
您可以使用递归CTE(递归公用表表达式)生成小时的集合。
接下来,您必须加入员工数据,其中劳动时间和劳动力关闭之间的小时数
保留仅添加CASE WHEN子句以计算小时数
看看这个解决方案:
declare @dataTable table(UNIT int, JOB varchar(5), EMPLOYEE nvarchar(50), LABOR_ON datetime2(0), LABOR_OFF datetime2(0))
INSERT INTO @dataTable
(UNIT, JOB, EMPLOYEE, LABOR_ON, LABOR_OFF)
VALUES
(398,'W9714',N'Ley',DATETIMEFROMPARTS(2015,12,16,11,46,39,0), DATETIMEFROMPARTS(2015,12,16,12,20,07,0)),
(398,'WSP06',N'Cervantes',DATETIMEFROMPARTS(2016,01,22,11,30,28,0), DATETIMEFROMPARTS(2016,1,22,12,25,56,0)),
(398,'DN3RT',N'Miller',DATETIMEFROMPARTS(2015,11,2,13,40,46,0), DATETIMEFROMPARTS(2015,11,2,15,01,12,0)),
(398,'N04TA',N'Kitzmiller',DATETIMEFROMPARTS(2015,10,20,16,22,02,0), DATETIMEFROMPARTS(2015,10,20,19,06,21,0)),
(398,'N2C54',N'Blackwell',DATETIMEFROMPARTS(2015,12,14,5,38,30,0), DATETIMEFROMPARTS(2015,12,14,10,34,46,0)),
(398,'NP02M',N'Perryman',DATETIMEFROMPARTS(2015,10,31,5,20,49,0), DATETIMEFROMPARTS(2015,10,31,12,53,43,0));
WITH hourCTE as (SELECT 0 as [HourNo]
UNION ALL
SELECT [HourNo] + 1 FROM hourCTE WHERE [HourNo] < 23
),
DataWithHours as (
SELECT UNIT
,JOB
,EMPLOYEE
,dateadd(hour,HourNo,cast(cast(LABOR_ON as date) as datetime)) as Hour_of_day
,LABOR_ON
,LABOR_OFF
,hourNo
FROM hourCTE
join @dataTable on [HourNo] between DATEPART(HOUR,LABOR_ON) and DATEPART(HOUR,LABOR_OFF))
SELECT UNIT
,JOB
,EMPLOYEE
,Hour_of_day
,
cast(CASE WHEN DATEPART(HOUR,LABOR_ON) = HourNo
THEN
DATEDIFF(SECOND,LABOR_ON,DATEADD(HOUR, 1, Hour_of_day))/cast(3600.0 as decimal)
WHEN DATEPART(HOUR,LABOR_OFF) = HourNo
THEN
DATEDIFF(SECOND,Hour_of_day,LABOR_OFF)/cast(3600.0 as decimal)
ELSE
1.000
END as decimal(6,5)) as Labor_Hours
FROM DataWithHours
order by unit, EMPLOYEE, HourNo