简单示例
问题是“如何按值对行进行分组,然后按频率将发生次数分成带有计数和平均值的桶。” 这里是手动完成的玩具示例,并取得了平均值:
带有值的月份,这里的每个数字表示一行。
Jan 12 24 60 150 320 488
Feb 8 16 40 100 220
Mar 4 8 20 310
总体数据
Month Count Avg Min Max
Jan 6 176 12 488
Feb 5 77 8 220
Mar 4 86 4 310
相同的原始数据,但包含更多数据,其中包括重复的值和更广泛的范围。
Jan 12 12 12 12 24 24 60 60 150 320 488 500
Feb 8 8 8 8 8 16 40 100 220 440 1100
Mar 4 8 8 8 8 20 20 20 20 310
总体数字
Month Count Avg Min Max
Jan 12 140 12 500
Feb 11 178 8 1100
Mar 10 43 4 310
其中之一数据集划分成3个桶的模拟
Month Count Avg Min Max Bucket
Jan 4 12 12 12 0
Jan 4 42 24 60 1
Jan 4 365 150 500 2
...and so on for Feb and Mar
我只是猜测以上模型中的桶会如何分配。
这基本上就捕捉到了我尝试做的事情。按月份名称(在我的实际情况中是从_to_node)进行分组,将结果行分成桶,然后为每个桶获取最小值、最大值、平均值和计数。听起来像是一个数据透视表(pivot)?
真实表格设置
以下是我正在获取供稿的表格结构:
CREATE TABLE IF NOT EXISTS data.edge_event (
id uuid,
inv_id uuid,
facility_id uuid,
from_node citext,
to_node citext,
from_to_node citext,
from_node_dts timestamp without time zone,
to_node_dts timestamp without time zone,
seconds integer,
cycle_id uuid
);
持续时间是以秒为单位预先计算的,目前感兴趣的区域仅限于from_to_node名称。因此,可以将示例视为
CREATE TABLE IF NOT EXISTS data.edge_event (
from_to_node citext,
seconds integer
);
原始数据
在edge_event
表中,大约有300K个事件行,其中包含159个不同的from_to_node
值。有些只在少数edge_event
记录中找到,有些则在成千上万个记录中找到。这样太多了,无法提供良好的样本。但是为了使问题更容易理解,from_to_node
可能是:
Boxing_Assembly 1256
表示“将该零件从装箱阶段移动到装配阶段需要1256秒”。对于“Boxing_Assembly”,我们可能有其他10,000条不同持续时间的记录。
目标
我们希望从每个from_to_node
中获得两个内容。对于像“Boxing_Assembly”这样的内容,我正在尝试做到以下两点:
将耗时分为桶,例如20个桶。这是制作直方图所需的。
对于每个桶,获取以下内容:
- edge_event行的计数
- 桶内avg(seconds)
- 桶内min/first_value(seconds)
- 桶内max/last_value(seconds)
因此,我们正在查看持续时间以寻找聚类,然后从任何常见聚类中获取原始秒数。
尝试过的方法
我尝试了很多不同的代码,但都没有成功。似乎这是一个需要GROUP BY
和/或窗口函数的问题。由于我的结果与目标相差甚远,所以肯定有些东西我没有弄懂。
我知道我没有提供样本数据,这使得帮助变得更加困难。但我猜我缺少一些概念。基本上,我想知道如何按from_to_node
和seconds
拆分edge_event
数据。考虑到from_to_nodes
的巨大范围,我试图根据它们自己的最小值/最大值单独对每个桶进行分组。
非常感谢您的帮助。
草稿尝试
我开发了一条查询语句,有点可行,但并非完全正确。这是我的原始发布帖子的编辑版本。
WITH
min_max AS
(
SELECT from_to_node,
min(seconds),
max(seconds)
FROM edge_event
GROUP BY from_to_node
)
SELECT edge_event.from_to_node,
width_bucket (seconds, min_max.min, min_max.max, 99) as bucket, -- Bucket are counted from 0, so 9 gets you 10 buckets, if you have enough data.
count(*) as frequency,
min(seconds) as seconds_min,
max(seconds) as seconds_max,
max(seconds) - min(seconds) as bucket_width,
round(avg(seconds)) as seconds_avg
FROM edge_event
JOIN min_max ON (min_max.from_to_node = edge_event.from_to_node)
WHERE min_max.min <> min_max.max AND -- Can't have a bucket with an upper and lower bound that are the same.
edge_event.from_to_node IN (
'Boxing_Assembly',
'Assembly_Waiting For QA')
GROUP BY edge_event.from_to_node,
bucket
ORDER BY from_to_node,
bucket
我得到的结果看起来相当不错:
from_to_node bucket frequency seconds_min seconds_max bucket_width seconds_avg
Boxing_Assembly 1 912 17 7052 7035 3037
Boxing_Assembly 2 226 7058 13937 6879 9472
Boxing_Assembly 3 41 14151 21058 6907 16994
Boxing_Assembly 4 16 21149 27657 6508 23487
Boxing_Assembly 5 4 28926 33896 4970 30867
Boxing_Assembly 6 1 37094 37094 0 37094
Boxing_Assembly 7 1 43228 43228 0 43228
Boxing_Assembly 10 2 63666 64431 765 64049
Boxing_Assembly 14 1 94881 94881 0 94881
Boxing_Assembly 16 1 108254 108254 0 108254
Boxing_Assembly 37 1 257226 257226 0 257226
Boxing_Assembly 40 1 275140 275140 0 275140
Boxing_Assembly 68 1 471727 471727 0 471727
Boxing_Assembly 100 1 696732 696732 0 696732
Assembly_Waiting For QA 1 41875 1 18971 18970 726
Assembly_Waiting For QA 9 1 207457 207457 0 207457
Assembly_Waiting For QA 15 1 336711 336711 0 336711
Assembly_Waiting For QA 38 1 906519 906519 0 906519
Assembly_Waiting For QA 100 1 2369669 2369669 0 2369669
一个问题在于这些桶的大小并不均匀...它们看起来有点奇怪。我也尝试过指定10、20或100个桶,但结果相似。我希望有一种更好的方法来分配数据到桶中,以及有一种方法可以让空的桶变成零条目桶。
width_bucket
就是我想要的... 我在之前发布的失败示例中尝试过它。 - Morris de Oryx