【问题标题】:Conditional time-series data aggregation条件时间序列数据聚合
【发布时间】:2016-06-14 04:28:54
【问题描述】:

我有一个关系数据库(postgres),其中包含一个包含时间序列指标的表。每行由 - obj_id, metric_id, timestamp, value

假设我有 3 个感兴趣的代码指标 - 1、4、5。我想过滤掉所有对象,对于相同的时间戳(假设所有指标的时间戳都在固定的时间间隔内),指标 1

一个更具体的例子:

obj_id       metric_id         timestamp        value
------------------------------------------------------
1             1                83827             9
1             4                83827             2
1             5                83827             1
2             1                73261             11
2             4                73261             2
2             5                73261             5
1             1                92381             24
1             4                92381             10
1             5                92381             100
2             1                38239             7
2             4                38239             3
2             5                38239             4

预期的结果是:

obj_id     timestamp
---------------------
  1         83827
  2         38239

我正在尝试创建一个高效的查询来做。这就是我的想法,以便为相同的时间戳获得 4 + 5 的总和,但我不确定将这些查询粘合在一起的最佳方法是什么:

SELECT obj_id, timestamp, sum(value) AS x
FROM metric
WHERE metric_id = 4 OR metric_id = 5
group by obj_id, timestamp

我不知道如何添加到这个查询指标 1(我们应该单独查询),然后通过 obj_idtimestamp 过滤掉结果。

我考虑过可能使用自连接,通过时间戳连接同一张表的两个内部选择。

【问题讨论】:

    标签: postgresql time-series aggregate-functions


    【解决方案1】:

    SQL Fiddle

    booleaninteger 的转换产生 0 或 1

    select obj_id, timestamp
    from metric
    where metric_id in (1,4,5)
    group by obj_id, timestamp
    having
        sum(value * (metric_id in (4,5))::integer) < 10
        and
        sum(value * (metric_id = 1)::integer) < 10
    

    【讨论】:

    • 绝对精彩,工作起来就像一个魅力,我什至可以阅读它。谢谢!
    【解决方案2】:

    也许这可以做得更好,但这感觉很好理解(需要 9.4+):

    WITH x AS(
      SELECT 
        obj_id,
        timestamp,
        min(value) FILTER (WHERE metric_id = 1) as metric1,
        min(value) FILTER (WHERE metric_id = 4) as metric4,
        min(value) FILTER (WHERE metric_id = 5) as metric5
      FROM metric
      GROUP BY obj_id, timestamp
    )
      SELECT obj_id, timestamp
      FROM x
      WHERE metric1 < 10
        AND (metric4 + metric5) < 10
    

    【讨论】:

    • 使用元组 (2, 1, 73261, 1) 失败
    • 那是因为 metric1 > 10... 这不是要求吗?
    • FWIW,查询中的数据框在最后一列中给出的值为 11 而不是 1
    • 我的意思是如果那个元组被插入到表中。
    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2019-07-13
    • 2021-04-02
    • 2021-12-20
    • 1970-01-01
    • 2017-03-07
    • 2012-12-09
    相关资源
    最近更新 更多