Запрос к базе данных для создания временной диаграммы - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть таблица логинов в следующей (упрощенной) структуре:

id | login_time
---------
1  | 2019-02-04 18:14:30.026361+00
2  | 2019-02-04 22:10:19.720065+00
3  | 2019-02-06 15:51:53.799014+00

Теперь я хочу сгенерировать диаграмму следующим образом:

https://prnt.sc/mifz6y

В основномЯ хочу показать логины за последние 48 часов.

Мой текущий запрос:

SELECT count(*), date_trunc('hour', login_time) as time_trunced FROM user_logins
WHERE login_time > now() - interval '48' hour
GROUP BY time_trunced
ORDER BY time_trunced DESC

Это работает, если есть записи для каждого часа.Однако, если в течение часа не будет входов, не будет выбранная запись, например:

time_trunced | count
---------------------
12:00        | 1
13:00        | 2
15:00        | 3
16:00        | 5

Мне потребуется непрерывный запрос, чтобы я мог просто поместить значения счетчика в массив:

time_trunced | count
---------------------
12:00        | 1
13:00        | 2
14:00        | 0 <-- This is missing
15:00        | 3
16:00        | 5

Исходя из этого, я могу просто преобразовать результат запроса в массив типа [1, 2, 0, 3, 5] и передать его моему внешнему интерфейсу.

Возможно ли это с postgresql? Или мне нужно реализовать собственную логику?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Я думаю, я бы сделал:

select gs.h, count(ul.login_time)
from generate_series(date_trunc('hour', now() - interval '48 hour', date_trunc('hour', now()), interval '1 hour'
                    ) gs(h) left join
     user_logins ul
     on ul.login_time >= gs.h and
        ul.login_time < gs.h + interval '1 hour'
group by gs.h
order by gs.h;
0 голосов
/ 08 февраля 2019

Это почти наверняка можно немного привести в порядок, но должно дать вам несколько идей.Реквизит для зажима для generate_series() наконечника:

SELECT t.time_trunced,coalesce(l.login_count,0) as logins 
FROM
(
 -- Generate an inline view with all hours between the min & max values in user_logins table
 SELECT date_trunc('hour',a.min_time)+ interval '1h' * b.hr_offset as time_trunced
 FROM (select min(login_time) as min_time from user_logins) a
 JOIN (select generate_series(0,(select ceil((EXTRACT(EPOCH FROM max(login_time))-EXTRACT(EPOCH FROM min(login_time)))/3600) from user_logins)::int) as hr_offset) b on true
) t
LEFT JOIN 
 (
 -- OP's original query tweaked a bit
 SELECT count(*) as login_count, date_trunc('hour', login_time) as time_trunced
 FROM user_logins
 GROUP BY time_trunced
) l on t.time_trunced=l.time_trunced
order BY 1 desc;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...