Я уверен, что на это уже был дан ответ, но я не могу найти его в деталях, которые мне нужны.
Для аналитической системы мне нужно иметь возможность группировать строки и возвращать их на диаграмму, сгруппированные по минутам , часам, день, месяц или год. Я правильно работаю (пример кода ниже).
SELECT COUNT( DISTINCT user_id ) , `hour` , `timestamp` FROM tracking_request WHERE site_id = '3' AND `timestamp` < '2011-08-31 04:05:45' AND `timestamp` > '2011-08-29 22:00:00' GROUP BY `hour` , `day` , `month` , `year` ORDER BY `timestamp` ASC
Проблема в том, что, как и большинство диаграмм, мне нужно заполнить пробелы, где нет данных (например, никаких строк за последние 3 минуты). Я читал о создании «таблицы календаря» и присоединении к этим данным, но как я могу сделать это эффективно для каждой шкалы (например, год будет намного проще, чем минута, так как в таблице потребуется много строк)? Если это помогает, есть столбец для каждого в таблице (например, вы видите, что есть «час», «день» и т. Д.).
РЕДАКТИРОВАТЬ:
Я закончил тем, что использовал PHP для этого, используя пустой массив, а затем заполнил его. Если бы кто-нибудь мог подумать обо всем (или в основном) SQL-решении для этого, это было бы более удивительным.
В этом ответе я расскажу, как создавать таблицы календаря.
Создайте три таблицы в течение нескольких дней, часов и минут:
CREATE TABLE days ( day DATE, PRIMARY KEY (day) ) CREATE TABLE hours ( hour INT, PRIMARY KEY (hour) ) CREATE TABLE minutes ( minute INT, PRIMARY KEY (minute) )
Заполните таблицу часов цифрами от 0 до 23 и таблицей минут с цифрами от 0 до 59. Чтобы заполнить таблицу дней, вы можете создать следующую процедуру:
CREATE PROCEDURE make_days(IN start_date DATE, IN end_date DATE) BEGIN DECLARE curr_date DATE; SET curr_date = start_date; WHILE curr_date <= end_date DO INSERT IGNORE INTO days(day) VALUES(curr_date); SET curr_date = DATE_ADD(curr_date, INTERVAL 1 DAY); END WHILE; END
Вы можете вызвать эту процедуру для создания таких дней:
CALL make_days('2011-01-01','2012-12-31');
Теперь вы можете создавать значения за каждую минуту в заданный интервал времени, используя запрос, подобный следующему:
SELECT YEAR(day) AS year, MONTH(day) AS month, DAYOFMONTH(day) AS day, hour, minute FROM days, hours, minutes WHERE CAST(CONCAT(day,' ',hour,':',minute) AS DATETIME) BETWEEN '2011-08-31 22:00' AND '2011-09-01 10:00' ORDER BY year, month, day, hour, minute
Обычно это делается в хранилищах данных, имея размер даты, который содержит список всех возможных дат. Вы выполняете ВНЕШНЮЮ СОБЛЮДЕНИЕ к размеру даты, а COALESCE – к 0.