在我们公司的工厂中,有一个物理过程,该过程具有两个阶段的开始和两个阶段的完成。当窗口小部件开始进入过程时,将创建一个包含窗口小部件ID和时间戳(DateTimeCreated)的新记录,一旦窗口小部件完全进入该过程,就会在同一记录的不同字段中记录另一个时间戳(DateTimeUpdated)。时间间隔大约是几分钟。
类似地,当窗口小部件开始退出过程时,将创建另一个包含窗口小部件ID和DateTimeCreated的记录,当窗口小部件完全退出过程时,将填充DateTimeUpdated。在当前表设计中,“退出”记录与“输入”记录是无法区分的(尽管给定的窗口小部件ID仅出现一次或两次,因此View可以利用这一事实来进行区分,但现在暂时忽略它)。
窗口小部件的整个处理过程需要几天的时间,但这对讨论并不重要。重要的是,退出流程时的时间间隔总是比进入时长。因此,一组非常简化的,虚构的排序间隔值可能看起来像这样:
1、2、2、3、3、3、3、3、3、3、3、4、6、7、7、7、7、8、8、8、8、10、10、10
您可以看到3分钟标记附近的间隔出现一个峰值(“输入”),而7/8分钟标记附近的间隔出现一个峰值(“出口”)。我还排除了5分钟的间隔,以证明进入间隔和退出间隔可以视为互斥的。
我们希望通过使用查询来确定进入和退出数据点集群的本地平均值,来每天监控流程中每个阶段的性能。因此,从概念上讲,两个数据集可以在总体平均值的任一侧进行拆分(在本例中为5.375),然后为拆分以下的值(2.75)和拆分上方的另一个平均值(8)计算平均值。使用上面的数据(随机分布),平均值在下面的图表中以虚线表示。
我当前的方法是使用两个Common Table Expressions,然后使用最后的三表联接查询。看起来还可以,但我忍不住感觉会更好。有人愿意提供替代方法或其他意见吗?
WITH cte_Raw AS
(
SELECT
DATEDIFF(minute, DateTimeCreated, DateTimeUpdated) AS [Interval]
FROM
MyTable
WHERE
DateTimeCreated > CAST(CAST(GETDATE() AS date) AS datetime) -- Today
)
, cte_Midpoint AS
(
SELECT
AVG(Interval) AS Interval
FROM
cte_Raw
)
SELECT
AVG([Entry].Interval) AS AverageEntryInterval
, AVG([Exit].Interval) AS AverageExitInterval
FROM
cte_Raw AS [Entry]
INNER JOIN
cte_Midpoint
ON
[Entry].Interval < cte_Midpoint.Interval
INNER JOIN
cte_Raw AS [Exit]
ON
[Exit].Interval > cte_Midpoint.Interval
答案 0 :(得分:1)
我认为您的查询不会产生准确的结果。您的两个let ordered = workoutData.sorted { string1, string2 in
guard let date1 = formatter.date(from: string1), let date2 = formatter.date(from: string2) else { return false }
return date1 < date2
}
正在产生大量的行,从而使平均值下降。它们可能看起来正确(因为其中一个小于另一个),但是您确实进行了计数,因此您会发现查询中的计数与样本数据无关。
如果您只是寻找小于总体平均值且大于总体平均值的平均值,那么您可以使用窗口功能:
JOIN
答案 1 :(得分:0)
我决定发布自己的答案,因为在撰写本文时,两个提议的答案都将无法运行。但是,我删除了JOIN语句,并使用了Gordon提出的CASE语句方法。
我还将DATEDIFF结果乘以1.0,以防止对AVG函数的结果进行舍入。
WITH cte_Raw AS
(
SELECT
1.0 * DATEDIFF(minute, DateTimeCreated, DateTimeUpdated) AS [Interval]
FROM
MyTable
WHERE
DateTimeCreated > CAST(CAST(GETDATE() AS date) AS datetime) -- Today
)
, cte_Midpoint AS
(
SELECT
AVG(Interval) AS Interval
FROM
cte_Raw
)
SELECT AVG(CASE WHEN cte_Raw.Interval < cte_Midpoint.Interval THEN cte_Raw.[Interval] END) AS AverageEntryInterval,
AVG(CASE WHEN cte_Raw.Interval > cte_Midpoint.Interval THEN cte_Raw.[Interval] END) AS AverageExitInterval
FROM cte_Raw CROSS JOIN cte_Midpoint
此解决方案无法满足弗拉基米尔(Vladimir)表示出场与出场间隔离散不均匀的理论陷阱,因为在实践中我们可以确信不会发生这种情况。