Средний интервал между временными метками в массиве - PullRequest
0 голосов
/ 03 февраля 2019

В базе данных PostgreSQL 9.x у меня есть столбец, который является массивом типа timestamp.Каждый массив имеет от 1..n отметок времени.

Я пытаюсь извлечь средний интервал между всеми элементами в каждом массиве.

Я понимаю, что использование оконной функции в исходной таблице может бытьидеальный способ решения этой проблемы, но в этом случае я пытаюсь сделать это как операцию над массивом.

Я рассмотрел несколько других вопросов, которые пытаются вычислить скользящее среднее для другого столбца и т. д., илиavg (средняя дата списка временных меток).

Для пример средний интервал, который я ищу для массива с тремя элементами, подобными этому:

'{"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 голосов
/ 03 февраля 2019

Один из многих возможных способов: отложить, присоединиться, в боковом подзапросе:

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 <> скрипка здесь

[INNER] JOIN в подзапросе производит именно набор комбинаций, относящихся к интервалам между элементами.

Я получаю 371 days 14:37:06.587543, а не '- 368d' ,Кстати.

Связано с более подробным объяснением:

Вы также можете только unnestодин раз и используйте оконные функции lead() или lag(), но вы пытались избежать оконных функций.И вам нужно убедиться в исходном порядке элементов в любом случае ...

(Нет функции массива , которую вы могли бы использовать напрямую, чтобы получить то, что вынужно - в случае, если вы надеялись на это.)

Альтернатива с 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 в подзапросе.

...