在 PostgreSQL 9.x 数据库中,我有一列是时间戳类型的数组。每个数组有 1..n 个时间戳。
我正在尝试提取每个数组中所有元素之间的平均间隔。
我知道在源表上使用窗口函数可能是解决这个问题的理想方法,但在这种情况下,我试图将其作为对数组的操作来执行。
我查看了其他几个试图计算另一列等的移动平均值或 avg(时间戳列表的中值日期)的问题。
对于示例,我在具有 3 个元素的数组上寻找的平均间隔如下:
'{"2012-10-09 17:04:05.710887"
,"2013-10-18 22:30:08.973749"
,"2014-10-22 22:18:18.885973"}'::timestamp[]
会是:
-368d
想知道是否需要通过函数解压数组?
最佳答案
许多可能的方法之一:在横向子查询中unnest、join、avg:
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<> fiddle here
子查询中的 [INNER] JOIN
生成与 between 元素的间隔相关的一组组合。
我得到 371 天 14:37:06.587543
,不是 '-368d',顺便说一句。
相关,有更多解释:
您也可以只取消嵌套一次并使用 window functions lead()
or lag()
,但您试图避免使用窗口函数。并且在任何情况下都需要确保元素的原始顺序......
(没有 array function 你可以直接使用来获得你需要的东西 - 如果你希望那样的话。)
CTE 的替代方案
可能仍然只嵌套一次(即使在避免窗口函数的情况下):
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
子句。
关于sql - 数组中时间戳之间的平均间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54505036/