sql - 如何使用 percentile_disc() 和窗口计算移动中位数?
问题描述
该窗口正在使用 COUNT、AVG 等,但不适用于 percentile_disc
SELECT
x,
COUNT(*) OVER w AS w_count, -- fine
AVG(x) OVER w AS avg_x, -- fine
percentile_disc(0.5) within group (order by x) OVER w AS mdn_x -- BUG!
FROM t
WINDOW w AS (ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
ORDER BY 1
(已编辑),
- PostgreSQL v10.12 在 "OVER" 或附近出现语法错误。
- PostgreSQL v12.2 说有序集聚合 percentile_disc 不支持 OVER
似乎这是不可能的......有一些解决方法吗?也许是带有子查询的横向连接。
解决方案
我只是想到了另一种可能。我们可以创建一个聚合并像内置的avg
或count
.
让我们从一个聚合器开始:
create function median_sfunc (
state integer[], data integer
) returns integer[] as
$$
begin
if state is null then
return array[data];
else
return state || data;
end if;
end;
$$ language plpgsql;
然后是终结者:
create function median_ffunc (
state integer[]
) returns double precision as
$$
begin
return (state[(array_length(state, 1) + 1)/ 2] + state[(array_length(state, 1) + 2) / 2]) / 2.;
end;
$$ language plpgsql;
当然,供应商(初始状态)将是空查询。因此我们得到聚合:
create aggregate median (integer) (
sfunc = median_sfunc,
stype = integer[],
finalfunc = median_ffunc
);
现在,无论您使用什么窗口,您都可以优雅地调用它:
select x,
count(*) over w as w_count,
avg(x) over w as avg_x,
median(x) over w as mdn_x
from tmp t
window w as (order by x rows between 3 preceding and current row)
推荐阅读
- terminal - 如何在 IPython shell 上更改 iTerm2 的颜色?
- java - 在 if 块中,我的 for 循环不起作用,因此 1,2,32 被烘烤而 3 没有
- html - 删除页脚 Prestashop 上的 h4 标签
- javascript - 使用 {...state} 创建只修改一个字段的新对象实例在 React JS 中不起作用
- python - 进行批量文件写入或以较小的部分写入文件是否更快?
- swift - 快速转义反斜杠无法按预期工作
- java - 转换 Observable onError 并发出一个项目
- line-breaks - 如何使用 reStructuredText 创建新行?
- docker - 在使用 docker compose 3 启动我的应用程序之前,我应该如何确定 DB 已启动
- php - Android 应用内购买验证问题:无法解析代码,返回值始终为零