ежедневная группировка данных postgres по часам

#sql #postgresql

#sql #postgresql

Вопрос:

Привет, у меня есть такие таблицы

 services
    id | service_name
    1  | service1
    2  | service2
    3  | service3
  

и у сервисов много токенов

 token
    id     | generated_time          | token_name | service_id
    461087 | 2016-10-21 09:02:53.951 |  G1        | 1
    461088 | 2016-10-21 09:31:13.469 |  C1        | 1
    461089 | 2016-10-21 09:31:15.711 |  C2        | 2
    461090 | 2016-10-21 10:37:17.73  |  C3        | 2
    461091 | 2016-10-21 10:02:53.951 |  G2        | 1
    461092 | 2016-10-21 10:15:13.469 |  C4        | 1
    461093 | 2016-10-21 11:22:15.611 |  C5        | 3
    461094 | 2016-10-21 11:31:14.743 |  C6        | 3
  

и токен имеет отношение один к одному с token_queue

 token_queue
    serving_end_time        |  serving_start_time      | token_id
    2016-10-21 09:04:45.681 |  2016-10-21 09:03:49.05  | 461087 
    2016-10-21 09:33:49.035 |  2016-10-21 09:32:07.996 | 461088 
    2016-10-21 09:34:42.431 |  2016-10-21 09:32:27.134 | 461089 
    2016-10-21 10:39:57.775 |  2016-10-21 10:38:37.428 | 461090
    2016-10-21 10:04:49.715 |  2016-10-21 10:03:09.972 | 461091
    2016-10-21 10:17:28.268 |  2016-10-21 10:16:06.946 | 461092
    2016-10-21 11:23:36.036 |  2016-10-21 11:22:30.233 | 461093
    2016-10-21 11:32:32.876 |  2016-10-21 11:31:27.044 | 461094
  

теперь я хочу отобразить минимальное / максимальное время, затрачиваемое всеми службами в течение 24 часов, на основе generated_time таблицы токенов. min / max здесь рассчитывается по

 MIN(token_queue.serving_end_time - token_queue.serving_start_time)
MAX(token_queue.serving_end_time - token_queue.serving_start_time) 
  

например

     hour -  2016-10-21 09:00:00
       service1
         min - 00:01:06
         max - 00:05:00
       service2
          min - 00:01:40
          max - 00:03:00
      service3
          min - 00:01:02
          max - 00:03:12

    hour -  2016-10-21 10:00:00
       service1
         min - 00:01:20
         max - 00:02:50
       service2
          min - 00:01:30
          max - 00:03:45
      service3
          min - 00:02:02
          max - 00:05:12
  

Я пробовал это

 SELECT date_trunc('hour', t.generated_time) AS hour,
       t.service_id AS service,
       min(tq.serving_end_time - tq.serving_start_time) AS min,
       max(tq.serving_end_time - tq.serving_start_time) AS max
FROM token t
     JOIN token_queue tq
        ON t.id = tq.token_id
GROUP BY service,hour;
  

но из этого я могу печатать только так

 hour - 2016-10-21 09:00:00
  service1
     min - 00:01:06
     max - 00:05:00
hour - 2016-10-21 09:00:00
  service2
     min - 00:01:40
     max - 00:03:00
hour - 2016-10-21 10:00:00
  service1
     min - 00:01:06
     max - 00:05:00
hour - 2016-10-21 10:00:00
  service2
     min - 00:01:30
     max - 00:03:45
  

спасибо за любую помощь и предложения.

Ответ №1:

ну, я справился с этим, сгруппировав результат массива

 foreach($min_max_avg as $mma){
    $hour = $mma->hour;
        if (isset($result[$hour])) {
                $result[$hour][] = $mma;
        } else {
                 $result[$hour] = array($mma);
                }
}
  

Ответ №2:

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

Я предлагаю добавить service_name для упрощения печати и упорядочить результат запроса сначала по часам, а затем по service_name (sqlfiddle)

 select date_trunc('hour', t.generated_time) as hour,
       s.service_name as service,
       min(tq.serving_end_time - tq.serving_start_time) as min,
       max(tq.serving_end_time - tq.serving_start_time) as max
from token t
join token_queue tq on t.id = tq.token_id
join services s on s.id = t.service_id
group by service, hour
order by hour, service
  

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

 $current_hour = 0;
foreach ($min_max_avg as $mma) {
    if ($mma->hour != $current_hour) {
        echo "hour - $mma->hourn";
        $current_hour = $mma->hour;
    }

    echo "    $mma->servicen";
    echo "        min - $mma->minn";
    echo "        max - $mma->maxn";
}