按月,日,小时+间隔和孤岛分组

时间:2018-11-13 16:38:01

标签: sql postgresql subquery query-optimization gaps-and-islands

我需要计算(百分比)状态在一天,几小时或一个月(工作时间)内持续多长时间。

我将表格简化为这个表格:

| date                      | status    |
|-------------------------- |--------   |
| 2018-11-05T19:04:21.125Z  | true      |
| 2018-11-05T19:04:22.125Z  | true      |
| 2018-11-05T19:04:23.125Z  | true      |
| 2018-11-05T19:04:24.125Z  | false     |
| 2018-11-05T19:04:25.125Z  | true      |
....

我需要得到这个结果(取决于参数):

几个小时:

| date                      | working_time |
|-------------------------- |--------------|
| 2018-11-05T00:00:00.000Z  | 14           |
| 2018-11-05T01:00:00.000Z  | 15           |
| 2018-11-05T02:00:00.000Z  | 32           |
|...                        | ...          |
| 2018-11-05T23:00:00.000Z  | 13           |

几个月:

| date                      | working_time |
|-------------------------- |--------------|
| 2018-01-01T00:00:00.000Z  | 14           |
| 2018-02-01T00:00:00.000Z  | 15           |
| 2018-03-01T00:00:00.000Z  | 32           |
|...                        | ...          |
| 2018-12-01T00:00:00.000Z  | 13           |

我的SQL查询如下:

 SELECT date_trunc('month', date)                                         as date,
       round((EXTRACT(epoch from sum(time_diff)) / 25920) :: numeric, 2) as working_time
FROM (SELECT date,
             status as current_status,
             (lag(status, 1) OVER (ORDER BY date)) AS previous_status,
             (date -(lag(date, 1) OVER (ORDER BY date))) AS time_diff
      FROM table
     ) as raw_data
WHERE current_status = TRUE AND previous_status = TRUE
GROUP BY date_trunc('month', date)
ORDER BY date;

,它工作正常,但速度很慢。关于优化有什么想法吗? Maybse使用Row_Number()函数吗?

1 个答案:

答案 0 :(得分:0)

尝试一下:

   SELECT t.month_reference as date,
            round(  sum(if(t_aux.status,1,0))  / 25920) :: numeric, 2) as working_time 

#我假设您使用此数字,因为这是系统的正常运行时间60 * 18 * 24,

#如果我想要一个月中的总秒数60 * 60 * 24 * day(Last_day(t.month_reference))

,我会使用它
FROM (SELECT date_trunc('month', t.date) as month_reference
          FROM table
         ) as t
    left join table t_aux
    on t.month_reference=date_trunc('month', t_aux.date) 

因此,当我们按月份分组时,sum()只会找到真实的并具有引用月份的行

   and t_aux.date < 
    (select t1.date 
    from table t1 
    where t.month_reference=date_trunc('month', t1.date) 
    and t1.status=false 
    order by t1.date asc limit 1 )

我添加了它,因此它只会选择正确的行,直到在同一月份引用中找到状态为false的行为止

    GROUP BY t.month_reference
    ORDER BY t.month_reference;