将PostgreSQL数据分组在输出中不超过N个值

时间:2017-02-09 14:13:50

标签: sql postgresql grouping aggregate-functions

我需要快速加载图表数据。数据位于日期-Y表中:

CREATE TABLE (
    id serial primary key,
    date timestamp not null,
    y1 double precision,
    y2 double precision,
    y3 double precision,
    y4 double precision,
    ....................
    yN double precision
);

为了简化这个问题,我可以说我只加载日期(X轴)和Y1(Y轴)。

图表包含水平N点并具有可变缩放。 X轴包含从mindate到maxdate的点。 mindate和maxdate的值取决于当前的缩放和平移位置。

为了快速加载数据,我需要使用任何聚合函数(MIN,MAX,AVG)执行动态数据分组,这样我就可以获得从mindate到maxdate范围内的N个聚合记录。

数据应按相等的时间间隔分组,即每5秒钟,每3分钟一次,具体取决于当前的图表比例。

如何使用PostgreSQL实现这一目标?

样品

select date, "1_2_pt100_x_1" from ob_data where "1_2_pt100_x_1" is not null order by date

13414记录:

"2016-12-08 12:13:41";44.5
"2016-12-08 12:16:42";44.7000007629395
"2016-12-08 12:19:43";44.9000015258789
"2016-12-08 12:22:44";45.2999992370606
"2016-12-08 12:25:44";45.5
"2016-12-08 12:30:11";45.9000015258789
"2016-12-08 12:33:12";45.5999984741211
"2016-12-08 12:36:12";45.9000015258789
"2016-12-08 12:39:13";46.2000007629395
"2016-12-08 12:42:14";46.5
"2016-12-08 12:45:15";46.5999984741211
"2016-12-08 12:48:15";46.9000015258789
"2016-12-08 12:51:16";47
"2016-12-08 12:54:16";47.0999984741211
"2016-12-08 12:57:17";47.4000015258789
"2016-12-08 13:00:17";47.4000015258789
"2016-12-08 13:03:18";47.7000007629395
"2016-12-08 13:06:18";47.7999992370606
"2016-12-08 13:09:19";47.7999992370606
"2016-12-08 13:12:19";47.7999992370606
"2016-12-08 13:15:20";48.0999984741211
"2016-12-08 13:18:20";48.0999984741211
"2016-12-08 13:21:21";48
"2016-12-08 13:24:21";48.4000015258789
"2016-12-08 13:27:22";48.2999992370606
"2016-12-08 13:30:22";48.2000007629395
"2016-12-09 08:58:54";20.2999992370606
"2016-12-09 09:01:55";20.3999996185303
"2016-12-09 09:04:55";20.6000003814697
"2016-12-09 09:07:56";20.6000003814697
"2016-12-09 09:10:56";20.8999996185303
"2016-12-09 09:13:57";20.7000007629395
"2016-12-09 09:16:57";21.2999992370606
"2016-12-09 09:19:58";21.5
"2016-12-09 09:22:58";22
"2016-12-09 09:25:59";22.2000007629395
"2016-12-09 09:28:59";22.5
"2016-12-09 09:32:00";22.8999996185303
"2016-12-09 09:35:00";23.1000003814697
"2016-12-09 09:38:01";23.2999992370606
"2016-12-09 09:41:01";23.6000003814697
"2016-12-09 09:44:02";24.1000003814697
"2016-12-09 09:47:02";24.2999992370606
"2016-12-09 09:50:03";24.6000003814697
"2016-12-09 09:53:03";24.7999992370606
"2016-12-09 09:56:04";25.2000007629395
"2016-12-09 09:59:04";25.2999992370606
"2016-12-09 10:02:05";25.7000007629395
"2016-12-09 10:05:05";25.8999996185303
"2016-12-09 10:08:06";25.8999996185303
"2016-12-09 10:11:06";26.2999992370606
"2016-12-09 10:14:07";26.3999996185303
"2016-12-09 10:17:07";26.7999992370606

预期输出

对于前6行,缩放因子2,使用平均函数:

"2016-12-08 12:13:41";44,6000003814698
"2016-12-08 12:19:43";45,1000003814698
"2016-12-08 12:25:44";45,7000007629395

(我自己用计算器计算,所以不要问我相应的SQL查询。)

每个聚合结果取2行实际上并不是正确的方法。在mindate和maxdate之间的整个数据空间应该被分成N个相等的间隔,并且每个间隔应该被聚合。作为日期的总值,我应该采用每个间隔的第一个日期。

1 个答案:

答案 0 :(得分:2)

我导入了您的数据:

create table so6 (d timestamp,f float);
copy so6 from stdin delimiter ',';

这里ntile(27)意味着你必须将53乘以2得到27 - 如果你想要每两个聚合一行,如果你想要每五个,那么它将是无效的(11):

with p as (
         select *, ntile(27) over(order by d) n
         from so6
         order by d
) select distinct min(d) over (partition by n),
         avg(f) over (partition by n)
from p
order by min;

         min         |       avg
---------------------+------------------
 2016-12-08 12:13:41 | 44.6000003814698
 2016-12-08 12:19:43 | 45.1000003814697
 2016-12-08 12:25:44 | 45.7000007629395
 2016-12-08 12:33:12 |            45.75
 2016-12-08 12:39:13 | 46.3500003814698
 2016-12-08 12:45:15 |            46.75
 2016-12-08 12:51:16 | 47.0499992370605
 2016-12-08 12:57:17 | 47.4000015258789
 2016-12-08 13:03:18 |            47.75
 2016-12-08 13:09:19 | 47.7999992370606
 2016-12-08 13:15:20 | 48.0999984741211
 2016-12-08 13:21:21 | 48.2000007629395
 2016-12-08 13:27:22 |            48.25
 2016-12-09 08:58:54 | 20.3499994277954
 2016-12-09 09:04:55 | 20.6000003814697
 2016-12-09 09:10:56 | 20.8000001907349
 2016-12-09 09:16:57 | 21.3999996185303
 2016-12-09 09:22:58 | 22.1000003814697
 2016-12-09 09:28:59 | 22.6999998092652
 2016-12-09 09:35:00 | 23.1999998092652
 2016-12-09 09:41:01 | 23.8500003814697
 2016-12-09 09:47:02 | 24.4499998092652
 2016-12-09 09:53:03 |               25
 2016-12-09 09:59:04 |             25.5
 2016-12-09 10:05:05 | 25.8999996185303
 2016-12-09 10:11:06 | 26.3499994277954
 2016-12-09 10:17:07 | 26.7999992370606
(27 rows)