我想计算Greenplum 中 列的 滚动中位数 ,即如下:
| x | rolling_median_x | | -- + ---------------- | | 4 | 4 | | 1 | 2.5 | | 3 | 3 | | 2 | 2.5 | | 1 | 2 | | 6 | 2.5 | | 9 | 3 |
x是一个整数,每行rolling_median_x显示x当前行和前一行的中位数。例如第三行rolling_median_x = median(4, 1, 3) = 3。
x
rolling_median_x
rolling_median_x = median(4, 1, 3) = 3
到目前为止我发现的事情:
median
median(x) OVER(RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
percent_rank
nth_value
事实上,我找不到合适的文档,有关这些文档可以在Greenplum中用作框架窗口函数…
我正在使用Greenplum 4.3.4.0(基于Postgres 8.2.15),不幸的是更新不是一种选择。
一句话-维基百科的一篇引文:ORDER BY
ORDER BY是对结果集中的行进行排序的唯一方法。 没有此子句,关系数据库系统可以按任何顺序返回行。如果需要排序,则必须在应用程序发送的SELECT语句中提供ORDER BY。尽管某些数据库系统允许在子选择或视图定义中指定ORDER BY子句,但该显示不起作用。视图是逻辑关系表, 关系模型要求一个表是一组行,这意味着没有排序顺序。
由于您需要计算当前 行和前一行 的中位数,因此表中必须有一个附加行, 该 行定义 了行的顺序, 并且可以用来确定给定行之前的行和之后的行。 让我们说这样的一id列:
id
| id | x | rolling_median_x | |----|---|------------------| | 1 | 4 | 4 | | 2 | 1 | 2.5 | | 3 | 3 | 3 | | 4 | 2 | 2.5 | | 5 | 1 | 2 | | 6 | 6 | 2.5 | | 7 | 9 | 3 |
如果您不能使用解析函数,请尝试使用纯SQL。 本文介绍了使用SQL计算中位数的各种方法。 我认为,亨德森的中位数将最适合我们的需求:
SELECT CASE COUNT(*) % 2 WHEN 0 -- even sized table THEN (P1.part_wgt + MIN(CASE WHEN P2.part_wgt > P1.part_wgt THEN P2.part_wgt ELSE NULL END))/2.0 ELSE P1.part_wgt --odd sized table END AS median FROM Parts AS P1, Parts AS P2 GROUP BY P1.part_wgt HAVING COUNT(CASE WHEN P1.part_wgt >= P2.part_wgt THEN 1 ELSE NULL END) = (COUNT(*) + 1) / 2;
只需将每行的查询作为一个依赖子查询运行,一般的想法是这样的:
SELECT t.*, ( SELECT .... Henderson's query FROM table x WHERE x.id <= t.id ...... ) As our_median FROM table t
您可以在此演示中找到示例实现
SELECT t.*, ( SELECT CASE COUNT(*) % 2 WHEN 0 -- even sized table THEN (P1.x + MIN(CASE WHEN P2.x > P1.x THEN P2.x ELSE NULL END))/2.0 ELSE P1.x --odd sized table END AS median FROM Table333 AS P1, Table333 AS P2 WHERE p1.id <= t.id AND p2.id <= t.id GROUP BY P1.x HAVING COUNT(CASE WHEN P1.x >= P2.x THEN 1 ELSE NULL END) = (COUNT(*) + 1) / 2 ) as Our_median FROM Table333 t; | id | x | rolling_median_x | our_median | |----|---|------------------|------------| | 1 | 4 | 4 | 4 | | 2 | 1 | 2.5 | 2.5 | | 3 | 3 | 3 | 3 | | 4 | 2 | 2.5 | 2.5 | | 5 | 1 | 2 | 2 | | 6 | 6 | 2.5 | 2.5 | | 7 | 9 | 3 | 3 |
这个查询可能会很慢-这是您必须拥有古代版本的PostgreSQL所要付出的代价