【发布时间】:2020-04-11 14:13:54
【问题描述】:
使用 Postgres 11.6,我正在尝试分析一些事件数据。目标是找到具有特定名称的所有事件的持续时间,然后将 每个 拆分为大小均匀的存储桶。我们正在寻找特定事件“聚集”的任何时间。我正在编辑我的问题,因为具体情况可能会掩盖我要问的内容。
简单示例
问题是“如何按值对行进行分组,然后按频率将出现次数拆分为具有计数和平均值的每个存储桶的存储桶。”这是一个带有四舍五入平均值的手工玩具示例:
有值的月份,这里的每个数字代表一行。
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
我只是在猜测桶在上面的模型中会如何分裂。
这几乎可以捕捉到我想要做的事情。按月份名称分组(在我的实际案例中为 from_to_node),将结果行拆分为存储桶,然后获取每个存储桶的最小值、最大值、平均值和计数。它开始听起来像一个支点(?)
真实表设置
这是我正在为其获取提要的表的结构:
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 秒。”在这里,我们可能还有 10,000 条不同持续时间的“Boxing_Assembly”的其他记录。
目标
我们在每个from_to_node 中寻找两个东西。对于像 Boxing_Assembly 这样的东西,我正在尝试这样做:
将秒数排序到桶中,比如 20 个桶。这是一个直方图。
对于每个存储桶,获取 edge_event 行数 桶内的平均(秒) 桶内的 min/first_value(seconds) 桶内的 max/last_value(seconds)
因此,我们希望绘制持续时间图表以查找集群,然后从任何常见集群中获取原始秒数。
我尝试过的
我尝试了很多不同的代码,但都没有成功。 GROUP BY 和/或窗口函数似乎是个问题。有些东西我没有得到,因为我的结果离目标还很远。
我知道我没有提供示例数据,因此很难提供帮助。但我猜我缺少的是一个 ++ 概念。差不多,我想知道如何按 from_to_node 然后按秒拆分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 个存储桶,并得到类似的结果。我希望有一种更好的方法可以将数据分配到我丢失的存储桶中,并且有一种方法可以使用零条目存储桶而不是间隙。
【问题讨论】:
-
您可能想查看 Postgres width_bucket 函数。还发布示例数据 - 作为文本而不是图像 - 并且该数据的预期结果将极大地提高您获得令人满意的答案。
-
感谢您的评论,我刚刚添加了一个带有数据(作为文本)的模拟示例,以更好地理解这个想法。而且,是的,我怀疑
width_bucket是我想要的……我在之前发布的失败示例中尝试过。 -
我更新了我的问题,草稿比我原来的损坏示例效果更好。
标签: postgresql pivot-table grouping histogram window-functions