我一直在研究一些SQL代码以实时测量某些生产数据的效率。快速背景介绍:
操作员将输入特定子装配体的数据。该数据如下所示:
ID PO W/S Status Operator TotalTime Date
60129515_2000_6_S025 107294 S025 Completed A 38 05/08/2020
60129515_2000_7_S025 107294 S025 Completed A 46 05/08/2020
60129515_2000_8_S025 107294 S025 Completed A 55 05/08/2020
60129515_2025_6_S020 107295 S020 Completed B 58 05/08/2020
60129515_2025_7_S020 107295 S020 Completed B 47 05/08/2020
60129515_2025_8_S020 107295 S020 Completed B 45 05/08/2020
60129515_2000_1_S090 107294 S090 Completed C 33 05/08/2020
60129515_2000_2_S090 107294 S090 Completed C 34 05/08/2020
60129515_2000_3_S090 107294 S090 Completed C 21 05/08/2020
相关的列是Operator
,TotalTime
和Date
(请注意,日期存储为varchar(50)
,因为这样可以更好地与Microsoft PowerApps配合使用)。
我需要做的是:
此计算将在每次查询运行时更改。这将允许拉出此查询的Microsoft PowerApp实时刷新效率度量。我已经刺了一下-见下文:
SELECT
md.Operator,
CASE
WHEN DATEADD(HOUR, -5, GETUTCDATE()) > CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '7:00' AND GETDATE() < CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '15:45'
THEN (SUM(isNull(md.TotalTime, 0)) + SUM(isNull(md.DelTime, 0))) * 1.0 / DATEDIFF(MINUTE, CONVERT(DATETIME, CONVERT(DATE, DATEADD(HOUR, -5, GETUTCDATE()))) + '7:00' , DATEADD(HOUR, -5, GETUTCDATE())) * 100.0
ELSE (SUM(isNull(md.TotalTime, 0)) + SUM(isNull(md.DelTime, 0))) / 420 * 100.0
END AS OpEfficiency
FROM
[Master Data] AS md
WHERE
md.[Date] = CONVERT(varchar(50), DATEADD(HOUR, -5, GETUTCDATE()), 101)
GROUP BY
md.Operator
注:DelTime
是有关延迟时间的另一列。我还将转换为UTC时间,以避免在转移到PowerApps时出现任何时区问题。
但是,这效率极低。我假设这是因为Date
需要每一次转换为日期时间。如果我的计算列已经转换了日期,效果会更好吗?还是有更好的方法来计算自某个时间以来经过的时间?
谢谢。
您可以采取一些措施来大大提高效率。首先,您要确保SQL在选择行时可以进行简单的比较,因此,从[Date]字段不是日期的字符串开始,计算与日期匹配的字符串。
第二,提前计算您的班次分钟数(完整班次为540分钟,或者在上午7点精确缩小为0,因此您不必在每一行中都计算分钟数。
第三,在对运算符求和时,请在分钟数上使用一个简单的总和,然后根据该总和以及您预先计算的班次到目前为止的分钟来计算效率。
[一个注释-在我的示例中,我正在铸造分钟,直到FLOAT为止,也许不是最好的类型,但是比其他十进制类型(如DECIMAL(18,6))或其他类型更清晰。选择可以显示所需比例的东西。
我的示例使用通用表表达式生成该日期字符串和到目前为止的分钟数FLOAT,这很好,因为它适合直接查询,视图,函数或存储过程,但是如果您愿意,可以使用DECLARE变量。
通过对预先计算出的TargetDate字符串使用[Date]字符串上的INNER JOIN进行过滤,我确保在对任何数据进行任何数学运算之前,将数据集缩减为最少的记录。您肯定会想要INDEX [Date],以便在表格填满时保持此速度。
所有这些都应该提供一个非常快速的查询,祝您好运
with cteNow as ( --Calculate once, up front - date as string, minutes elapsed as FLOAT (or any non-integer)
SELECT CASE WHEN 60*DATEPART(HOUR, GETUTCDATE())+DATEPART(MINUTE, GETUTCDATE()) > 60*21
--4PM in UTC-5, expressed in minutes
THEN CONVERT(float,(16-7)*60) --minutes in (4 PM-7 AM) * 60 minutes/hour
ELSE --Assume nobody is running this at 6 AM, so ELSE = between 7 and 4
CONVERT(float,60*DATEPART(HOUR, GETUTCDATE()) + DATEPART(MINUTE, GETUTCDATE()) - ((7+5)*60))
--Minutes since midnight minus minutes from midnight to 7 AM, shifted by
--UTS offset of 5 hours
END as MinutesToday --Minutes in today's shift so far
, FORMAT(DATEADD(HOUR,-5,GETUTCDATE()),'MM/dd/yyyy') as TargetDate --Date to search for
--as a string so no conversion in every row comparison. Also, index [Date] column
)
SELECT md.Operator, SUM(md.TotalTime) as TotalTime, SUM(md.TotalTime) / MinutesToday as Efficiency
FROM [Master Data] AS md INNER JOIN cteNow as N on N.TargetDate = md.[Date]
GROUP BY md.Operator, MinutesToday
顺便说一句,您没有为午餐或上午7点之前的跑步津贴,所以我也忽略了这些。我认为都可以在cteNOW中解决这两个问题,而不会增加太多复杂性。