文档中心MogDBMogDB StackUqbar

文档:v2.0

支持的版本:

其他版本:

percentile

功能描述

percentile算子支持时序表/非时序表的分位数计算,用于返回数据排序后位于第N个百分位数的值。

在排序的基础上percentile_cont提供了按照分位数确定最近邻元素,并按照分位数比率插值输出的功能。percentile_disc则不进行插值,直接输出原始数据。

例如:

CREATE TIMESERIES TABLE weather(time timestamp TSTIME, city text TSTAG,province text TSTAG, temperature float) ;

有 5 条时序数据,如下所示:

time 00:00:00 00:01:00 00:15:00 00:36:00 00:45:00
value 10.5 20.2 30.7 40.1 50.9

已有的取值分别对应0、0.25、0.5、0.75与1的分位数。

现计算各分位数的取值,计算结果如下:

使用插值时,使用聚合函数名:percentile_cont

Percentile_cont 0 0.5 0.8 1
Value 10.5 30.7 42.26 50.9

不使用插值时,使用聚合函数名:percentile_disc

Percentile_disc 0 0.5 0.8 1
Value 10.5 30.7 40.1 50.9

这两个算子的差异如下:

  • percentile_disc为不连续的百分位:返回第一个在排序位置中等于或超过指定分数的输入值。

  • percentile_cont为连续的百分位:返回一个值对应于排序中指定的分数, 如果需要,插入到临近的输入项之间。

在上述示例中,当分位数为0.8时,不存在与之对应的原始值,使用percentile_cont需要对结果进行插值,插值方式应与PostgreSQL一致。

插值算法:

(hi-lo)*((row_num-1)*percentile – floor((row_num-1)*percentile))

上述示例中,hi=50.9,lo=40.1,row_num=5,percentile=0.8,故插值结果为10.8*0.2+40.1=42.26。

使用percentile_disc时不会插值,而是跳过指定行数据后返回第一个值:

skip_row_num = ceil(row_num * percentile) - 1

在该计算值大于1的情况下才会跳过排序后的行,以满足在percentile=0下不做跳过返回第一个值。

percentile_disc和percentile_cont均支持ARRAY作为输入,单次处理多个百分位并返回数组结果。该功能相较于多次执行percentile算子,仅需要一次排序就可以得到所有输出,既方便用户使用又减少了重复扫描排序的资源消耗。

语法格式

-- 插值
percentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY double precision )double precision
percentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY interval )interval

-- 插值ARRAY
percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY double precision )double precision[]
percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY interval )interval[]

-- 非插值
percentile_disc ( fraction double precision ) WITHIN GROUP ( ORDER BY anyelement ) → anyelement

-- 非插值ARRAY
percentile_disc ( fractions double precision[] ) WITHIN GROUP ( ORDER BY anyelement ) → anyarray

参数说明

参数名 类型 属性 释义
fractions FLOAT8OID 必选 分位数的数值表示,如:0.5表示中位数
sort_expression FLOAT8OID 或 INTERVALOID 必选 需要排序并获取分位数的列,对于需要插值场景列类型仅支持数值和时间间隔。
sort_expression Anyelement 必选 需要排序并获取分位数的列,对于不需要插值的场景,列类型支持timestamp、timestamptz、date、time、timetz、numeric、float4、float8。

约束

  1. 需要插值的percentile_cont仅支持可排序的Float类型与Interval类型。

  2. 不需要插值的percentile_disc支持可排序的类型,如:timestamp、timestamptz、date、time、timetz、numeric、float4、float8。

  3. 顺序聚合函数需要指定WITHIN GROUP (ORDER BY sort_expression)。

示例

Uqbar=# SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY value) AS median
FROM float_data;
 median
--------
   30.7
(1 row)

Uqbar=# SELECT percentile_cont(0.8) WITHIN GROUP (ORDER BY value)
FROM float_data;
 percentile_cont
-----------------
           42.26
(1 row)

Uqbar=# SELECT percentile_disc(1.5) WITHIN GROUP (ORDER BY value) FROM float_data;
ERROR:  percentile value 1.5 is not between 0 and 1

Uqbar=# SELECT percentile_disc(-1) WITHIN GROUP (ORDER BY value) FROM float_data;
ERROR:  percentile value -1 is not between 0 and 1

Uqbar=# SELECT percentile_cont(ARRAY[0,0.5,0.8,1]) WITHIN GROUP (ORDER BY duration) AS median FROM interval_data;
                         median
--------------------------------------------------------
 {"1 day 06:00:00","2 days","2 days 09:36:00","3 days"}
(1 row)

Uqbar=# SELECT percentile_disc(ARRAY[0,0.5,0.8,1]) WITHIN GROUP (ORDER BY duration) AS median FROM interval_data;
                         median
--------------------------------------------------------
 {"1 day 06:00:00","2 days","2 days 06:00:00","3 days"}
(1 row)
Copyright © 2011-2024 www.enmotech.com All rights reserved.