2016-03-01 4 views
1

У меня есть реляционная БД (postgres) с таблицей, которая содержит метрики временного ряда. Каждая строка состоит из - obj_id, metric_id, timestamp, valueУсловная агрегация данных временного ряда

Предположим, у меня есть 3 метрики интереса с кодами - 1, 4, 5. Я хотел бы отфильтровать все объекты, которые для одной и той же метки времени (предположим, что метка времени для всех показателей имеет фиксированные интервалы), имеют метрику 1 < 10 и (метрическая 4 + метрика 5) < 10 с определенной меткой времени, что это произошло событие.

Более конкретный пример:

obj_id  metric_id   timestamp  value 
------------------------------------------------------ 
1    1    83827    9 
1    4    83827    2 
1    5    83827    1 
2    1    73261    11 
2    4    73261    2 
2    5    73261    5 
1    1    92381    24 
1    4    92381    10 
1    5    92381    100 
2    1    38239    7 
2    4    38239    3 
2    5    38239    4 

Ожидаемый результат будет:

obj_id  timestamp 
--------------------- 
    1   83827 
    2   38239 

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

SELECT obj_id, timestamp, sum(value) AS x 
FROM metric 
WHERE metric_id = 4 OR metric_id = 5 
group by obj_id, timestamp 

Я не уверен, как добавить к этому запросу метрику 1 (которую мы должны запросить отдельно), а затем отфильтровать результаты на obj_id и timestamp.

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

ответ

3

SQL Fiddle

Бросок от boolean до integer выходов 0 или 1

select obj_id, timestamp 
from metric 
where metric_id in (1,4,5) 
group by obj_id, timestamp 
having 
    sum(value * (metric_id in (4,5))::integer) < 10 
    and 
    sum(value * (metric_id = 1)::integer) < 10 
+0

Абсолютно блестящий и работает как шарм, и я даже могу его прочитать. Благодаря! – Avi

0

Вероятно, это можно было бы сделать лучше, но это чувствовал аккуратным, чтобы понять (требует 9.4+):

WITH x AS(
    SELECT 
    obj_id, 
    timestamp, 
    min(value) FILTER (WHERE metric_id = 1) as metric1, 
    min(value) FILTER (WHERE metric_id = 4) as metric4, 
    min(value) FILTER (WHERE metric_id = 5) as metric5 
    FROM metric 
    GROUP BY obj_id, timestamp 
) 
    SELECT obj_id, timestamp 
    FROM x 
    WHERE metric1 < 10 
    AND (metric4 + metric5) < 10 
+0

Сбой с кортежем '(2, 1, 73261, 1)' –

+0

Это потому, что metric1> 10 ... I Это требование? –

+0

FWIW, поле данных в Query дает значение в последнем столбце как 11, а не 1 –

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