sql - Postgres 按值更改分区/分组
问题描述
我想构建一个查询,它不是按值本身对数据进行分组,而是按行之间的值变化这一事实来分组数据。我将不胜感激任何帮助!这是一个例子:
假设我有一个具有这种结构的表:
create table events (
event_time timestamp,
source_id integer references source(id),
metric integer,
flagged boolean
);
和以下样本数据:
source_id | event_time | metric | flagged
-----------------------------------------
1 | 8:00 | 1 | t
1 | 8:10 | 15 | f
1 | 8:20 | 7 | t
1 | 8:30 | 3 | t
1 | 8:40 | 6 | f
1 | 8:50 | 10 | t
2 | 9:00 | 5 | t
我想查询metric
组的子组的平均值,但如果数据是有序的,则根据不会从一行更改为下一行source_id
的事实对这些子组进行分组。flagged
也就是说,在上面的示例中,我的意思不是group by source_id, flagged
,因为这只会为每个 提供两个组source_id
,而是将连续行分组,按时间排序,其中flagged
相邻行中的值相同。也就是说,我想有以下组:
group_number | source_id | flagged | avg(metric)
------------------------------------------------
1 | 1 | t | 1 -- group includes entry for 8:00 only
2 | 1 | f | 15 -- entry for 8:15 only
3 | 1 | t | 5 -- entries on 8:20 & 8:30, (7+3)/2
4 | 1 | f | 6 -- entry for 8:40 only
5 | 1 | t | 10 -- entry for 8:50 only
6 | 2 | t | 5 -- 9:00 from source_id = 2
group_number
输出中不需要,这里只是为了使大小写更清楚。此外,我不需要那些不是的条目flagged
——基本上它们只用于拆分组。
我试图用分区和ranks
和来做到这一点lags
,但到目前为止无济于事。将不胜感激任何帮助!谢谢你。
解决方案
这是一个差距和孤岛问题。一种解决方案使用行号的差异。
select source_id, flagged, avg(metric)
from (select e.*,
row_number() over (partition by source_id order by event_time) as seqnum_1,
row_number() over (partition by source_id, flagged order by event_time) as seqnum_2
from events e
) e
group by source_id, flagged, (seqnum_1 - seqnum_2);
这个工作的原因有点难以解释。我发现如果您运行子查询,您将看到行号之间的差异如何识别具有相同标志的相邻行组。
推荐阅读
- java - Jersey/Dropwizard 中的 Spring RequestContextHolder 是什么
- mongodb - MongoDB Bi 连接器无法更新 max_num_global_tables 系统变量
- android - 当我尝试在当前活动上使用适配器显示某些内容时,Android 应用程序会继续返回主活动 UI
- android - 在 UI 线程错误室数据库 Android Studio 上运行
- swift-package-manager - swiftpm 使用 binaryTarget 存档时出现错误“没有这样的模块”
- javascript - 如何在反应中使用axios发送文件和数据?
- javascript - 基于javascript循环显示或隐藏字段
- javascript - 尽管设置为默认格式化程序,但 Pretier 扩展程序不起作用
- code-signing - 使用标准代码签名证书建立信任需要多少次下载
- webpack - 共享包中的纱线工作区和 baseUrl