Я ждал, чтобы кто-нибудь еще вмешался, так как я не разбираюсь в mysql, и я считаю, что должно быть лучшее решение.
Основная проблема здесь - это способ построить таблицу часов в день. Отсутствие рекурсивной способности выбора в MySQL заставило меня создать таблицу с помощью объединения. Даты проще, если мы можем принять пропущенные дни, когда никто не вошел в эту дату. Если нет, то для продления дат можно использовать тот же трюк, что и с часами, например, на семь дней.
Перекрестное соединение создаст таблицу дат, каждая из которых будет иметь все 24 часа дня. Теперь нам нужно посчитать сеансы, которые были активны в данный момент. Для этого нам нужно усечь startTime до часовых границ и поместить объединенное время перекрестного соединения в усеченные startTime и endTime (для которых не требуется усечение). Наши данные наконец здесь.
Чтобы получить среднее значение за последние два месяца, просто включите этот выбор в еще один час группировки и вычислите avg (Users). Если вам действительно нужен один запрос для возврата обоих наборов данных, вы можете объединить этот запрос со средним запросом, где средний запрос будет возвращать ноль для даты.
Дополнительный отказ от ответственности: как уже говорилось ранее, я не знаю MySql. Я пытался написать функции преобразования даты и времени, используя онлайн-руководство. Возможно, с треском провалился, но я верю, что вы меня поправите. Я также не уверен насчет зарезервированных ключевых слов.
select days.date,
hour,
count (s.startTime) Users
from
(
(
select 0 hour
union
select 1 hour
union
select 2 hour
union
select 3 hour
union
select 4 hour
union
select 5 hour
union
select 6 hour
union
select 7 hour
union
select 8 hour
union
select 9 hour
union
select 10 hour
union
select 11 hour
union
select 12 hour
union
select 13 hour
union
select 14 hour
union
select 15 hour
union
select 16 hour
union
select 17 hour
union
select 18 hour
union
select 19 hour
union
select 20 hour
union
select 21 hour
union
select 22 hour
union
select 23 hour
) hours
cross join
(
-- We need date portion only
select distinct date(startTime) date from s
union select distinct date(endTime) from s
) days
)
left join s
-- date+hour, hopefully
on date_add(date, interval hour HOUR)
-- startTime is truncated to hour, hopefully
between date_sub(s.startTime interval minutes(s.startTime) MINUTE)
and s.endTime
-- last two months
where days.date between date_sub (now() interval 2 MONTH) and now()
group by days.date, hour
order by 1, 2