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

时间:2019-02-03 16:31:50

标签: sql arrays postgresql average intervals

在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

想知道是否需要通过函数将数组拆包吗?

1 个答案:

答案 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可以直接用来获取所需的东西,以防万一。)

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