Рассчитать разницу между двумя строками, усредненную по дням - PullRequest
0 голосов
/ 04 января 2019

У меня есть таблица items, у которой есть статус и день создания

+----+-----------+------------+
| id | status    | created    |
+----+-----------+------------+
| 1  | PROCESSED | 2018-12-01 |
+----+-----------+------------+
| 2  | PROCESSED | 2018-12-01 |
+----+-----------+------------+
| 3  | ABORTED   | 2018-12-01 |
+----+-----------+------------+

Существует соответствующая таблица item status, которая обновляется при изменении статуса

+----+---------+-----------+------------------+
| id | item_id | status    | created          |
+----+---------+-----------+------------------+
| 1  | 1       | RECEIVED  | 2018-12-01 10:00 |
+----+---------+-----------+------------------+
| 2  | 1       | PROCESSED | 2018-12-01 12:00 |
+----+---------+-----------+------------------+
| 3  | 2       | RECEIVED  | 2018-12-01 11:00 |
+----+---------+-----------+------------------+
| 4  | 2       | PROCESSED | 2018-12-01 12:00 |
+----+---------+-----------+------------------+
| 5  | 3       | RECEIVED  | 2018-12-01 13:00 |
+----+---------+-----------+------------------+
| 6  | 3       | ABORTED   | 2018-12-01 13:30 |
+----+---------+-----------+------------------+

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

Примерно так (продолжительность в секундах):

+------------+------------------+
| day        | avg_duration     |
+------------+------------------+
| 2018-12-01 | 5400             |
+------------+------------------+

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

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Используйте логический агрегат bool_and() для фильтрации прерванных элементов:

select date, avg(duration)
from (
    select created::date as date, item_id, extract(epoch from max(created)- min(created)) as duration
    from item_status
    group by created::date, item_id
    having bool_and(status <> 'ABORTED')
    ) s
group by date

    date    | avg  
------------+------
 2018-12-01 | 5400
(1 row) 
0 голосов
/ 04 января 2019

Для этого требуется 2 уровня агрегации: один раз для элемента и даты, а затем для даты.

select dt_created,avg(diff) as avg_diff
from (select item_id
            ,created::date as dt_created
            ,max(case when status = 'PROCESSED' then created end) - max(case when status = 'RECEIVED' then created end) as diff 
      from item_statuses 
      group by item_id,created::date
      having count(case when status = 'ABORTED' then 1 end) = 0
    ) t
group by dt_Created
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...