Mysql для выбора месячной записи, даже если данные не существуют

Я написал запрос для получения месячной записи в таблице пользователя следующим образом

SELECT COUNT( `userID` ) AS total, DATE_FORMAT( `userRegistredDate` , '%b' ) AS MONTH , YEAR( `userRegistredDate` ) AS year FROM `users` GROUP BY DATE_FORMAT( FROM_UNIXTIME( `userRegistredDate` , '%b' ) ) 

Вывод:

 total MONTH year --------------------------- 3 May 2013 2 Jul 2013 -------------------------- 

Ожидаемый результат:

 total MONTH year --------------------------- 0 Jan 2013 0 Feb 2013 0 Mar 2013 0 Apr 2013 3 May 2013 0 Jun 2013 2 Jul 2013 -------------------------- 

Мне нужно показать запись, даже если данные не существуют. Как это сделать?

Я не буду говорить об эффективности, так как я не тестировал ее против других методов, но без таблицы времен. Это кажется справедливым способом.

  SELECT COUNT(u.userID) AS total, m.month FROM ( SELECT 'Jan' AS MONTH UNION SELECT 'Feb' AS MONTH UNION SELECT 'Mar' AS MONTH UNION SELECT 'Apr' AS MONTH UNION SELECT 'May' AS MONTH UNION SELECT 'Jun' AS MONTH UNION SELECT 'Jul' AS MONTH UNION SELECT 'Aug' AS MONTH UNION SELECT 'Sep' AS MONTH UNION SELECT 'Oct' AS MONTH UNION SELECT 'Nov' AS MONTH UNION SELECT 'Dec' AS MONTH ) AS m LEFT JOIN users u ON MONTH(STR_TO_DATE(CONCAT(m.month, ' 2013'),'%M %Y')) = MONTH(u.userRegistredDate) AND YEAR(u.userRegistredDate) = '2013' GROUP BY m.month ORDER BY 1+1; 

Если вы создаете союз на основе формата даты, вы можете даже уменьшить работу и загрузить запрос.

  SELECT COUNT(u.userID) AS total, DATE_FORMAT(merge_date,'%b') AS month, YEAR(m.merge_date) AS year FROM ( SELECT '2013-01-01' AS merge_date UNION SELECT '2013-02-01' AS merge_date UNION SELECT '2013-03-01' AS merge_date UNION SELECT '2013-04-01' AS merge_date UNION SELECT '2013-05-01' AS merge_date UNION SELECT '2013-06-01' AS merge_date UNION SELECT '2013-07-01' AS merge_date UNION SELECT '2013-08-01' AS merge_date UNION SELECT '2013-09-01' AS merge_date UNION SELECT '2013-10-01' AS merge_date UNION SELECT '2013-11-01' AS merge_date UNION SELECT '2013-12-01' AS merge_date ) AS m LEFT JOIN users u ON MONTH(m.merge_date) = MONTH(u.userRegistredDate) AND YEAR(m.merge_date) = YEAR(u.userRegistredDate) GROUP BY m.merge_date ORDER BY 1+1; 

Live DEMO обоих запросов.

Возможно, вам понадобится таблица для хранения каждой записи месяца. Временная таблица может сделать трюк:

 drop table if extists temp_months; create temporary table temp_months month date, index idx_date(month); insert into temp_months values ('2013-01-31'), ('2013-02-28'), ... 

И теперь вы можете присоединиться к своим данным с помощью этой недавно созданной таблицы temp:

 SELECT COUNT( `userID` ) AS total, DATE_FORMAT( m.month , '%b' ) AS MONTH , YEAR( m.month ) AS year FROM months as m left join `users` as u on m.month = last_day(FROM_UNIXTIME(`userRegistredDate`, '%b' ) GROUP BY last_day(m.month); 

Обратите внимание, что вы можете поместить создание таблицы temp (и заполнить) в хранимую процедуру.

Я использую last_day для простоты, но вы можете использовать любую дату месяца, который вам нравится, если вы присоедините его правильно.

Надеюсь это поможет

  • MySQL: могу ли я сделать левое соединение и вытащить только одну строку из таблицы соединений?
  • Как добавить первичный ключ в таблицу MySQL?
  • Запрос на hibernate для получения конкретных столбцов
  • Как отлаживать время ожидания ожидания ожидания ожидания на сервере MySQL?
  • Невозможно выполнить операции манипуляции данными с помощью executeQuery ()
  • Клонирование базы данных MySQL в одном экземпляре MySql
  • Как изменить столбец MySQL, чтобы разрешить NULL?
  • Как сохранить IPv6-совместимый адрес в реляционной базе данных
  • В Apache Spark 2.0.0 можно ли получить запрос из внешней базы данных (а не захватить всю таблицу)?
  • Как получить имя пользователя и пароль MySQL?
  • Как преобразовать файл excel в базу данных mysql?
  • Давайте будем гением компьютера.