SQL服务器:运营商实时衡量效率
SQL Server : measuring real-time efficiency by operator
我一直在编写一些 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 配合使用) .
我需要做的是:
- 聚合按运算符
分组的"TotalTime"的总和
- 根据条件计算经过的时间:
- 如果在早上 7 点到下午 4 点之间,计算从当天早上 7 点开始经过的时间
- 如果下午4点以后,return当天早上7点到下午4点的总时间
- 将 SUM(TotalTime) 除以 TimeElapsed(又名第一个列表项/第二个列表项),以便粗略估计工作时数与一天中经过的小时数。
每次查询 运行 时,此计算都会更改。这将允许提取此查询的 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 时间转换回来,以避免在 t运行 转移到 PowerApps 时出现任何时区问题。
但是,这是非常低效的。我假设这是因为 Date
每次都需要转换为日期时间。如果我有一个已经转换日期的计算列,它会更好吗?或者有没有更好的方法来计算自某个时间以来经过的时间?
提前致谢。
您可以采取一些措施来显着提高效率。首先,您要确保 SQL 可以在选择行时进行简单比较,因此您将首先计算一个字符串以匹配您的日期,因为您的 [Date] 字段是字符串而不是日期。
其次,提前计算轮班的分钟数(整个班次为 540 分钟,或者正好在早上 7 点缩减为 0 分钟),这样您就不会计算每一行的分钟数。
第三,在对操作员求和时,对分钟使用简单的总和,并根据该总和和您预先计算的班次到目前为止的分钟数计算效率。
请注意 - 在我的示例中,我将到目前为止的分钟转换为 FLOAT,这可能不是最好的类型,但它比 DECIMAL(18,6) 等其他小数类型更清晰。选择能够显示您想要的比例的东西。
我的示例使用通用 Table 表达式生成该日期字符串和到目前为止的分钟数 FLOAT,这很好,因为它适合直接查询、视图、函数或存储过程,但您可以如果你愿意,可以改为声明变量。
通过针对预先计算的 TargetDate 字符串在 [Date] 字符串上使用 INNER JOIN 进行过滤,我确保在对任何内容进行任何数学运算之前将数据集削减到最少的记录。您肯定希望在 table 填满时索引 [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 中解决,而不会增加太多复杂性。
我一直在编写一些 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 配合使用) .
我需要做的是:
- 聚合按运算符 分组的"TotalTime"的总和
- 根据条件计算经过的时间:
- 如果在早上 7 点到下午 4 点之间,计算从当天早上 7 点开始经过的时间
- 如果下午4点以后,return当天早上7点到下午4点的总时间
- 将 SUM(TotalTime) 除以 TimeElapsed(又名第一个列表项/第二个列表项),以便粗略估计工作时数与一天中经过的小时数。
每次查询 运行 时,此计算都会更改。这将允许提取此查询的 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 时间转换回来,以避免在 t运行 转移到 PowerApps 时出现任何时区问题。
但是,这是非常低效的。我假设这是因为 Date
每次都需要转换为日期时间。如果我有一个已经转换日期的计算列,它会更好吗?或者有没有更好的方法来计算自某个时间以来经过的时间?
提前致谢。
您可以采取一些措施来显着提高效率。首先,您要确保 SQL 可以在选择行时进行简单比较,因此您将首先计算一个字符串以匹配您的日期,因为您的 [Date] 字段是字符串而不是日期。
其次,提前计算轮班的分钟数(整个班次为 540 分钟,或者正好在早上 7 点缩减为 0 分钟),这样您就不会计算每一行的分钟数。
第三,在对操作员求和时,对分钟使用简单的总和,并根据该总和和您预先计算的班次到目前为止的分钟数计算效率。
请注意 - 在我的示例中,我将到目前为止的分钟转换为 FLOAT,这可能不是最好的类型,但它比 DECIMAL(18,6) 等其他小数类型更清晰。选择能够显示您想要的比例的东西。
我的示例使用通用 Table 表达式生成该日期字符串和到目前为止的分钟数 FLOAT,这很好,因为它适合直接查询、视图、函数或存储过程,但您可以如果你愿意,可以改为声明变量。
通过针对预先计算的 TargetDate 字符串在 [Date] 字符串上使用 INNER JOIN 进行过滤,我确保在对任何内容进行任何数学运算之前将数据集削减到最少的记录。您肯定希望在 table 填满时索引 [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 中解决,而不会增加太多复杂性。