2016-10-11 5 views
1

Мне нужно выполнить некоторый статистический анализ с интервалами, то есть разницу между двумя полями datetime в таблице.Postgres: Статистические функции на временных интервалах даты

В соответствии с общей функциональной документацией here. Совокупность функционирует для MAX, MIN, AVG и т. Д., Т.е. общие агрегированные функции принимают аргументы для полей даты и времени.

Однако для более продвинутых статистических функций, таких как stddev_pop, var_pop, var_sam и std_samp вход поддерживается, как представляется, числовыми или подобными только. Хотя документация предполагает, что нет никакой разницы между этими двумя типами функций

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

Есть ли простой способ расчета этих параметров? и почему тип интервала не поддерживается аргументом? Эти типы статистических агрегатных функций являются единичными инвариантами?

P.S. Я не уверен, что могу извлечь эпоху и использовать ее, поскольку некоторые значения могут быть отрицательными.

+1

Разница между двумя полями даты и времени поражает меня как числовой. –

+0

Thats, что я также думал, однако разница - это интервал типа даты, и эти функции не принимают интервальные входы, avg делает, хотя это не имеет никакого смысла для меня. – Manquer

+1

@DanBracuk различие между двумя «timestamps» - это 'interval' –

ответ

1

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

Чтобы обойти эту проблему, уменьшите интервал до часов или минут или секунд (или что-то еще). Это оказывается намного проще, чем вычисление вручную, и это говорит о том, почему PostgreSQL не поддерживает такой расчет из коробки.

Во-первых, функция от PostgreSQL general mailing list

CREATE OR REPLACE FUNCTION interval_to_seconds(interval) 
RETURNS double precision AS $$ 
    SELECT (extract(days from $1) * 86400) 
     + (extract(hours from $1) * 3600) 
     + (extract(minutes from $1) * 60) 
     + extract(seconds from $1); 
$$ LANGUAGE SQL; 

Теперь мы можем принять стандартное отклонение простого набора интервалов.

with intervals (i) as (
    values (interval '1 hour'), (interval '2 hour'), (interval '3 hour'), 
     (interval '4 hour'), (interval '5 hour') 
) 
, intervals_as_seconds as (
    select interval_to_seconds(i) as seconds 
    from intervals 
) 
select stddev(seconds), stddev(seconds)/60 
from intervals_as_seconds 
 
in_sec    in_min 
double precision double precision 
-- 
5692.09978830308 94.8683298050514 

Вы можете проверить результаты, однако вам нравится.

Теперь предположим, что вам нужна часовая гранулярность вместо секунд. Очевидно, что выбор гранулярности зависит от приложения. Вы можете определить другую функцию, interval_to_hours(interval). Вы можете использовать очень похожий запрос для вычисления стандартного отклонения.

with intervals (i) as (
    values (interval '1 hour'), (interval '2 hour'), (interval '3 hour'), 
     (interval '4 hour'), (interval '5 hour') 
) 
, intervals_as_hours as (
    select interval_to_hours(i) as hours 
    from intervals 
) 
select stddev(hours) as stddev_in_hrs 
from intervals_as_hours 
 
stddev_in_hrs 
double precision 
-- 
1.58113883008419 

Значение стандартного отклонения в часах явно отличается от значения, в течение нескольких минут или в секундах. Но они измеряют то же самое. Дело в том, что «правильный» ответ зависит от гранулярности (единиц), которую вы хотите использовать, и есть много вариантов. (От микросекунд до столетий, я думаю.)

Также рассмотрите это утверждение.

select interval_to_hours(interval '45 minutes') 
 
interval_to_hours 
double precision 
-- 
0 

Это правильный ответ?Вы не можете сказать; правильный ответ зависит от приложения. Я могу представить приложения, которые хотели бы считать 45 минут, чтобы считаться 1 час. Я также могу представить приложения, которые хотели бы, чтобы 45 минут считались 1 часом для приблизительно расчетов, а также 0 часов для других расчетов.

И подумайте об этом вопросе. Сколько секунд в месяц? Выражение select interval '1' month; действительно; количество секунд зависит от количества дней в месяце.

И я думаю это почему PostgreSQL не поддерживает такой расчет из коробки. Правильный способ сделать это с помощью интервальных аргументов слишком зависим от приложения.

Позже. , ,

Я нашел это обсуждение в одном из списков рассылки PostgreSQL.

No stddev() for interval?

+1

Нет необходимости писать собственный 'interval_to_seconds()'. Это можно сделать, используя 'extract (epoch from ...)' –

+0

thx для подробного объяснения. Лист списка рассылки попал в поиск Google, но я не был уверен, почему такой хак, похоже, был нужен тогда. Различные единицы измерения меняют значения, особенно, поскольку время не является стандартным десятичным преобразованием. Предполагая, что по умолчанию говорят секунды, возможно, я думаю, это может быть нежелательно или разумно. – Manquer

+0

Я не могу проверить его, но вы можете попытаться вычислить результат как секунды, я использую thison Teradata: 'stddev (seconds) * interval '0000 00:00:00' second' – dnoeth

Смежные вопросы