在PostgreSQL 9.x数据库中,我有一列是timestamp类型的数组。每个数组都有1..n个时间戳。
我正在尝试提取每个数组中所有元素之间的平均间隔。
我知道在源表上使用窗口函数可能是解决此问题的理想方法,但是在这种情况下,我试图将其作为对数组的操作来实现。
我查看了其他几个问题,这些问题试图计算另一列等的移动平均值或平均值(时间戳列表的中位数)。
对于示例,我正在寻找具有3个元素的数组的平均间隔:
'{"2012-10-09 17:04:05.710887"
,"2013-10-18 22:30:08.973749"
,"2014-10-22 22:18:18.885973"}'::timestamp[]
将是:
-368d
想知道是否需要通过函数将数组拆包吗?
答案 0 :(得分:2)
一种可能的方式:嵌套,联接,横向子查询中的平均值:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (
SELECT avg(a2.ts - a1.ts) AS avg_intv
FROM unnest(t.arr) WITH ORDINALITY a1(ts, ord)
JOIN unnest(t.arr) WITH ORDINALITY a2(ts, ord) ON (a2.ord = a1.ord + 1)
) avg ON true;
db <>提琴here
子查询中的[INNER] JOIN
精确地生成与元素之间的间隔 相关的一组组合。
我得到371 days 14:37:06.587543
,而不是'-368d',
相关,带有更多说明:
您也只能嵌套一次并使用window functions lead()
or lag()
,但是您试图避免使用窗口功能。而且无论如何,您都需要确保元素的原始顺序...
(没有array function可以直接用来获取所需的东西,以防万一。)
可能只吸引一次嵌套(即使在避免使用窗口功能的情况下):
SELECT *
FROM tbl t
LEFT JOIN LATERAL (
WITH a AS (SELECT * FROM unnest(t.arr) WITH ORDINALITY a1(ts, ord))
SELECT avg(a2.ts - a1.ts) AS avg_intv
FROM a a1
JOIN a a2 ON (a2.ord = a1.ord +1)
) avg ON true;
但是我希望增加的CTE开销比不嵌套两次要花费更多。大多只是在子查询中演示WITH
子句。