Допустим, у меня есть таблица, заполненная каждым соединением, которое обращается к моему веб-сайту, включая следующую информацию:
- connection_id (int)
- start_datetime (datetime)
- end_datetime (datetime)
- device_type (int, идентификатор для доступа по мобильному телефону (1), p c (2), прочее (3), et c.)
Я хотел бы - в одном запросе - получить счет за каждую минуту дня всех соединений, которые начались до или в течение этой минуты И закончились в течение или после этой минуты. Так что любой, кто был активен в любое время в течение этой минуты. Я хочу посмотреть время начала 6 часов назад, чтобы не проверять всю таблицу. В течение одной минуты (2020-01-25 10:10:00) запрос будет выглядеть следующим образом:
SELECT SUM(CASE WHEN device_type=1 THEN 1 ELSE 0 END) AS Mobile,
SUM(CASE WHEN device_type=2 THEN 1 ELSE 0 END) AS PC,
SUM(CASE WHEN device_type=3 THEN 1 ELSE 0 END) AS Other FROM
connection_table WHERE start_datetime BETWEEN '2020-01-25 04:10:00' AND '2020-01-25 10:10:59'
AND end_datetime > '2020-01-25 10:10:00';
Один запрос работает нормально, поэтому я могу go каждую минуту дня и сделать этот запрос, но было бы здорово, если бы я мог сделать это в одном запросе вместо этого. Одиночный запрос, конечно, также должен возвращать столбец с той минутой, за которую он получил счет. У меня есть таблица с именем all_minutes с записью для каждой минуты следующих нескольких лет, потому что я где-то читал, что это обходной путь для получения возвращаемого значения для каждой минуты , даже если я не надену не обязательно иметь записи, соответствующие этой минуте в таблице . К этой таблице можно присоединиться, если это поможет.
Есть ли способ сделать это в одном запросе? Пример предпочтительного набора возвращаемых значений:
Datetime | Mobile | PC | Other
2020-01-25 00:00:00 | 30 | 120 | 17
2020-01-25 00:01:00 | 33 | 121 | 18
2020-01-25 00:02:00 | 38 | 122 | 18
2020-01-25 00:03:00 | 37 | 116 | 19
...
2020-01-25 23:59:00 | 30 | 120 | 17
Я пытался с подзапросом, но я не сделал его работать. Это была одна из моих попыток, но она теряет возможность использовать свой индекс, когда я пытаюсь передать ему all_minutes.the_datetime в качестве параметра "DT". Также я не могу вернуть 3 значения в подзапросе, и выполнение 3 отдельных подзапросов не является хорошим вариантом.
SELECT the_datetime as dt, (SELECT COUNT(*) FROM connection_table WHERE
start_datetime BETWEEN DATE_SUB(dt, INTERVAL 6 HOUR)
AND DATE_ADD(dt, INTERVAL 59 SECOND) AND end_datetime > dt) AS connections
FROM all_minutes WHERE the_datetime BETWEEN '2020-01-25 00:00:00' and '2020-01-25 23:59:59';
ОБНОВЛЕНИЕ: я также попытался, присоединившись к таблице all_minutes и к connection_table, как @ spencer7593 и @GMB предлагает , но это останавливает применение индекса моей таблицы соединений (start_datetime > end_datetime
), заставляя его проверять каждую строку в таблице (и это очень большая таблица). FORCE INDEX тоже не работает.