2016-06-20 2 views
0

У меня есть сбор данных каждую минуту и ​​хранится в базе данных Postgres. Я пытаюсь создать запрос, который покажет разницу в значении за этот 5-минутный период.Разница в PostgreSQL за период времени

Итак, где у меня есть следующие данные:

val   created_at   
115414.568 2016-06-18 18:29:53 
115443.656 2016-06-18 18:30:53 
115461.817 2016-06-18 18:31:53 
115494.406 2016-06-18 18:32:53 
115527.151 2016-06-18 18:33:53 
115550.096 2016-06-18 18:34:53 
115610.065 2016-06-18 18:35:53 
115640.957 2016-06-18 18:36:53 
115667.033 2016-06-18 18:37:53 
115683.302 2016-06-18 18:38:53 
115727.717 2016-06-18 18:39:53 
115748.331 2016-06-18 18:40:53 
115763.520 2016-06-18 18:41:53 
115795.607 2016-06-18 18:42:53 
115849.592 2016-06-18 18:43:53 
115871.538 2016-06-18 18:44:53 
115908.999 2016-06-18 18:45:53 
115923.776 2016-06-18 18:46:53 
115961.043 2016-06-18 18:47:53 
115988.369 2016-06-18 18:48:53 
116003.320 2016-06-18 18:49:53 
116056.299 2016-06-18 18:50:53 
116069.396 2016-06-18 18:51:53 
116092.485 2016-06-18 18:52:53 
116137.878 2016-06-18 18:53:53 
116162.937 2016-06-18 18:54:53 
116204.077 2016-06-18 18:55:53 
116235.593 2016-06-18 18:56:53 
116242.502 2016-06-18 18:57:53 
116285.713 2016-06-18 18:58:53 
116317.299 2016-06-18 18:59:53 
116340.120 2016-06-18 19:00:53 
116387.000 2016-06-18 19:01:53 

Я хотел бы следующую группировку:

2016-06-18 18:25:00 ... 
2016-06-18 18:30:00 166.409 
2016-06-18 18:35:00 138.266 
2016-06-18 18:40:00 160.668 
2016-06-18 18:45:00 147.300 
2016-06-18 18:50:00 147.778 
2016-06-18 18:55:00 136.043 
2016-06-18 19:00:00 ... 

Я сумел собрать следующие вместе:

SELECT 
    val, 
    first_value(val) over (partition by period_start) as first_value, 
    period_start, 
    created_at 
FROM (
    SELECT 
    date_trunc('minute', created_at) - (EXTRACT(MINUTE FROM created_at)::INTEGER % 5) * INTERVAL '1 minute' AS period_start, 
    concat(kwh, '.', LPAD(wh::text, 3, '0'))::FLOAT as val, 
    "readings"."created_at" 
    FROM 
    readings 
    WHERE 
    "readings"."created_at" between '2016-06-18 18:29:53' AND '2016-06-18 19:02:53' 
) s1 

Что дает мне следующее:

val   first_value period_start  created_at 
115414.568 115414.568 2016-06-18 18:25:00 2016-06-18 18:29:53.121609 
115443.656 115443.656 2016-06-18 18:30:00 2016-06-18 18:30:53.124389 
115461.817 115443.656 2016-06-18 18:30:00 2016-06-18 18:31:53.127074 
115494.406 115443.656 2016-06-18 18:30:00 2016-06-18 18:32:53.129728 
115527.151 115443.656 2016-06-18 18:30:00 2016-06-18 18:33:53.1324 
115550.096 115443.656 2016-06-18 18:30:00 2016-06-18 18:34:53.135078 
115610.065 115610.065 2016-06-18 18:35:00 2016-06-18 18:35:53.137708 
115640.957 115610.065 2016-06-18 18:35:00 2016-06-18 18:36:53.140347 
115667.033 115610.065 2016-06-18 18:35:00 2016-06-18 18:37:53.143023 
115683.302 115610.065 2016-06-18 18:35:00 2016-06-18 18:38:53.145754 
115727.717 115610.065 2016-06-18 18:35:00 2016-06-18 18:39:53.14852 
115748.331 115748.331 2016-06-18 18:40:00 2016-06-18 18:40:53.151326 
115763.520 115748.331 2016-06-18 18:40:00 2016-06-18 18:41:53.154003 
115795.607 115748.331 2016-06-18 18:40:00 2016-06-18 18:42:53.156723 
115849.592 115748.331 2016-06-18 18:40:00 2016-06-18 18:43:53.159454 
115871.538 115748.331 2016-06-18 18:40:00 2016-06-18 18:44:53.162127 
115908.999 115908.999 2016-06-18 18:45:00 2016-06-18 18:45:53.164743 
115923.776 115908.999 2016-06-18 18:45:00 2016-06-18 18:46:53.167401 
115961.043 115908.999 2016-06-18 18:45:00 2016-06-18 18:47:53.169997 
115988.369 115908.999 2016-06-18 18:45:00 2016-06-18 18:48:53.17265 
116003.320 115908.999 2016-06-18 18:45:00 2016-06-18 18:49:53.175299 
116056.299 116056.299 2016-06-18 18:50:00 2016-06-18 18:50:53.17797 
116069.396 116056.299 2016-06-18 18:50:00 2016-06-18 18:51:53.180955 
116092.485 116056.299 2016-06-18 18:50:00 2016-06-18 18:52:53.183606 
116137.878 116056.299 2016-06-18 18:50:00 2016-06-18 18:53:53.186317 
116162.937 116056.299 2016-06-18 18:50:00 2016-06-18 18:54:53.189088 
116204.077 116204.077 2016-06-18 18:55:00 2016-06-18 18:55:53.191821 
116235.593 116204.077 2016-06-18 18:55:00 2016-06-18 18:56:53.194513 
116242.502 116204.077 2016-06-18 18:55:00 2016-06-18 18:57:53.197222 
116285.713 116204.077 2016-06-18 18:55:00 2016-06-18 18:58:53.199996 
116317.299 116204.077 2016-06-18 18:55:00 2016-06-18 18:59:53.208784 
116340.120 116340.120 2016-06-18 19:00:00 2016-06-18 19:00:53.217547 
116387.000 116340.120 2016-06-18 19:00:00 2016-06-18 19:01:53.226262 

Таким образом, я предполагаю, что следующим шагом будет вычесть первое значение 2016-06-18 18:30:00 с первого 2016-06-18 18:35:00, но я не уверен, как сделайте это (возможно, используя функцию Window) - если нет более простого способа, который я пропускаю?

Любые советы, оцененные.

+0

добавить четкие и удалить столбцы '' created_at' над val' пожалуйста, –

+0

'ВЫБРАТЬ first_value (val) over (partition by period_start) как first_value, period_start' –

+0

, а затем 'select first_value, lag (first_value) over (partition by period_start) from (SELECT first_value (val) over (partition by period_start) как first_value, period_start –

ответ

0

На самом деле это было менее сложным, чем ожидалось.

Я уже знаю, сколько минут в 15-минутный период Каждое чтение, так что я просто использовал ИНЕКЕ, чтобы найти все строки, в которых это значение равно 0.

От там, я могу просто использовать функция LAG вычесть предыдущее значение и получить разницу

SELECT 
    val - (lag(val) over (order by created_at)) as diff, 
    val, 
    created_at 
FROM (
    SELECT 
    EXTRACT(MINUTE FROM created_at)::INTEGER % 5 as minutes_into_period, 
    concat(val, '.', LPAD(wh::text, 3, '0'))::FLOAT as val, 
    "readings"."created_at" 
    FROM 
    readings 
    WHERE 
    "readings"."created_at" between '2016-06-18 18:29:53' AND '2016-06-18 19:02:53' 
) s1 
WHERE minutes_into_period = 0 

дает мне

diff    val   created_at 
        115443.656 2016-06-18 18:30:53.124389 
166.409   115610.065 2016-06-18 18:35:53.137708 
138.266000000003 115748.331 2016-06-18 18:40:53.151326 
160.667999999991 115908.999 2016-06-18 18:45:53.164743 
147.300000000003 116056.299 2016-06-18 18:50:53.17797 
147.778000000006 116204.077 2016-06-18 18:55:53.191821 
136.042999999991 116340.12 2016-06-18 19:00:53.217547 
0

Это может быть проблема с повторной выборкой/интерполяцией. Вы хотите иметь значение каждые 5 минут, чтобы вы могли просто различать строки подряд с помощью оконной функции.

Повторная выборка и интерполяция - довольно распространенная проблема «науки о данных», но ее трудно решать в PostGres. This great articles дает много ответов на эту проблему. Большие идеи:

  • generate_series
  • linear_interpolate
  • оконные функции
Смежные вопросы