数组中时间戳之间的平均间隔

Average interval between timestamps in an array

在 PostgreSQL 9.x 数据库中,我有一列是时间戳类型的数组。每个数组有 1..n 个时间戳。

我正在尝试提取每个数组中所有元素之间的平均间隔。

我知道在源 table 上使用 window 函数可能是解决此问题的理想方法,但在这种情况下,我试图将其作为对数组的操作来执行。

我查看了其他几个试图计算另一列等的移动平均值或 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、在横向子查询中取平均值:

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 days 14:37:06.587543,而不是 '-368d',顺便说一句。

相关,更多解释:

  • PostgreSQL unnest() with element number

您也可以只取消嵌套一次并使用 window functions lead() or lag(),但您试图避免使用 window 函数。并且在任何情况下都需要确保元素的原始顺序...

(没有 array function 你可以直接使用来获得你需要的东西 - 如果你希望那样的话。)

CTE 的替代方案

可能只对 unnest 有吸引力(即使在避免 window 函数的同时):

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 子句。