【问题标题】:First value in a aggregated query聚合查询中的第一个值
【发布时间】:2014-09-22 18:02:20
【问题描述】:

我有一个表格,其中包含来自流程的一些统计值。表格格式如下:

CREATE TABLE data (
    process    integer   NOT NULL,
    time       timestamp NOT NULL
    first      double precision,
    last       double precision,
    first_time timestamp,
    last_time  timestamp
)

此表中的数据每分钟插入一次,包含聚合 最后一分钟的值。例如,对于进程 1,我们可以有 以下数据:

+---------------------------------------------------------------------------------+
|             process | time | first | last  | first_time | last_time             |
+---------------------------------------------------------------------------------+
| 1 | 2014-09-22 12:00:00 | 100 | 200 | 2014-09-22 12:00:00 | 2014-09-22 12:00:59 |
| 1 | 2014-09-22 12:01:00 | 104 | 152 | 2014-09-22 12:01:00 | 2014-09-22 12:01:59 |
| 1 | 2014-09-22 12:02:00 | 141 | 155 | 2014-09-22 12:02:10 | 2014-09-22 12:02:59 |
| 1 | 2014-09-22 12:03:00 | 122 | 147 | 2014-09-22 12:03:00 | 2014-09-22 12:02:45 |
+---------------------------------------------------------------------------------+

正如您在第三行中看到的,有时第一个值不是 分钟的第二个 0。在最后一次也发生这种情况(第四行)。

使用this page 中的 first 和 last 函数,以及 date_round 函数 来自this page,我想在 30 中选择给定进程的第一个值 分钟间隔。

当我尝试以下两个查询时,两个结果都是正确的。

SELECT
    date_round(time, '30 min'::interval) AS "time",
    first(first)
FROM
    data
WHERE
    process = 1
    AND
    time > '2014-09-20 00:00:00'
    AND
    time < '2014-09-22 18:00:00'
GROUP BY 1
ORDER BY 1

SELECT
    date_round(time, '30 min'::interval) AS "time",
    first(first) AS "value"
FROM (
    SELECT
        time,
        first
    FROM
        data
    WHERE
        process = 1
        AND
        time > '2014-09-20 00:00:00'
        AND
        time < '2014-09-22 18:00:00'
    ORDER BY 1
) A
GROUP BY 1
ORDER BY 1

我的问题是:为什么第一个查询在这种情况下有效? postgres 之前是否对数据进行排序 应用 group by 子句?

我的怀疑是因为“第一个”函数返回两个传递参数的第一个值。 如果数据没有排序,那么第一次调用“first”聚合函数 可以包含不正确顺序的值,导致无效值,对吧?

我可以安全地使用第一个查询还是应该使用第二个查询?

【问题讨论】:

    标签: sql postgresql group-by


    【解决方案1】:

    这是您真正想要的查询:

    SELECT distinct on (date_round(time, '30 min'::interval))
           date_round(time, '30 min'::interval) AS "time",
           first
    FROM data
    WHERE process = 1 AND
          time > '2014-09-20 00:00:00' AND
          time < '2014-09-22 18:00:00'
    ORDER BY date_round(time, '30 min'::interval), time;
    

    Postgres 不会在group by 之前进行排序——根据 SQL 的定义,没有数据库会这样做。碰巧先遇到最早的记录,但不能保证。事实上,我认为第二个版本也不能保证被订购(尽管我在这一点上找不到明确的 Postgres 文档)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-23
      • 2023-02-23
      • 1970-01-01
      • 2020-06-06
      • 2018-02-23
      • 1970-01-01
      • 2020-03-09
      相关资源
      最近更新 更多