我试图估计人们在一段时间内工作了多少小时。我想通过部门和他们在哪个领域展示这一点。现在我有了这个:
SELECT M.MemberDepartmentID,T.TaskName,
COUNT(DATEDIFF(HOUR, TT.StartTime, TT.EndTime)) 'Hours',
AVG(DATEDIFF(HOUR, TT.StartTime, TT.EndTime)) Average
FROM Member.TaskTracking TT
LEFT OUTER JOIN Member.Task T
ON TT.TaskID=T.TaskID
JOIN dbo.tblMember M
ON TT.MemberID=M.MemberID
WHERE M.FullTime=1
AND M.EmployeeSalary=1
AND (TT.StartTime >= '2013-10-01'
AND TT.EndTime < '2013-11-01')
GROUP BY M.MemberDepartmentID,T.TaskName
ORDER BY M.MemberDepartmentID,T.TaskName
我不知道如何确认它是否正确,但有些肯定会显示平均零,即使有工作时间。有些平均值高于工作小时数。例如,以下是我的一些结果:
MemberDepartmentID TaskName Hours Average
---------------------------------------------------
1 Packing 25 0
1 Picking 6 0
1 PreScanning 38 7
4 Picking 2 104
建议?
答案 0 :(得分:8)
首先,重要的是要注意DATEDIFF(HOUR)
返回一个整数,并不一定能很好地反映实际传递的时间。例如,这两者都产生1
:
SELECT DATEDIFF(HOUR, '03:59', '04:01'); -- 2 minutes (0.033333 hours)
SELECT DATEDIFF(HOUR, '03:01', '04:59'); -- 118 minutes (1.966666 hours)
这些都产生0:
SELECT DATEDIFF(HOUR, '03:01', '03:59'); -- 58 minutes (0.966666 hours)
SELECT DATEDIFF(HOUR, '03:01', '03:02'); -- 1 minute (0.016666 hours)
接下来,如果你给SQL Server整数划分,它将执行整数数学运算。意味着它将分裂,但它将丢弃任何剩余部分。这产生0:
SELECT 3/4;
即使它真的是0.75,如果它被四舍五入,它应该是1.(并非这些结果中的任何一个都特别有意义)。现在,将其扩展到平均值。
DECLARE @d1 TABLE(a INT);
INSERT @d1 VALUES(3),(4);
SELECT AVG(a) FROM @d1;
这会产生3,而不是3.5,你可能会期望。出于与上述相同的原因。
记住你的一些任务可能持续了59分钟,但仍然会产生0小时的差异,你可能会有4个任务,其中3个持续时间> 1小时,一个持续时间<1小时1小时。所以你的平均计算基本上是:
SELECT (1+1+1+0)/4;
如上所述,仍然会产生0。
如果你想要一个有意义的平均值,你应该计算花费的时间比按小时计算。例如,您可以在几分钟内执行datediff:
SELECT DATEDIFF(MINUTE, '03:01', '04:59');
这会产生118.如果你想以小时表示,你可以除以60.0(小数是重要的)或乘以1.0:
SELECT DATEDIFF(MINUTE, '03:01', '04:59')/60.0;
SELECT 1.0*DATEDIFF(MINUTE, '03:01', '04:59')/60;
这两者均收益率为1.966666。平均这样的结果更有意义。所以也许把你的表达改为:
Average = AVG(1.0*DATEDIFF(MINUTE, TT.StartTime, TT.EndTime)/60)
关于计数,不确定您尝试在那里做什么,但您可能希望对计算进行类似的调整和可能会考虑使用SUM
。如果您显示一些样本数据和您期望的结果,我们可以提供更多帮助。
此外,我建议不要使用'single quotes'
转义关键字别名 - 不推荐使用此语法的某些形式,并且它使您的别名看起来像字符串文字。首先,尽量不要使用关键字或其他无效标识符作为别名;但如果必须,请使用[square brackets]
来逃避它们。