2014-09-22 89 views
0

我有一个包含进程中某些统计值的表。该表具有以下格式:汇总查询中的第一个值

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使用的第一和最后的功能,和从所述this page功能date_round ,我想在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子句之前对数据进行排序?

我的疑问是因为“第一个”函数返回两个传递参数的第一个值。 如果数据未排序,则“第一个”聚合函数 中的第一个调用可能包含的值不正确,导致无效值,对不对?

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

回答

2

这是你真正想要的查询:

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文档)。