2013-07-29 36 views
6

我写了一个查询来获取一个月明智记录在用户表如下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 
-------------------------- 

即使数据不存在,我也需要显示记录。这个怎么做?

+0

基本上你想不存在个月(不存在,因为在你没有该月/年的记录),以显示当你没有记录用它 ? – Prix

+0

@Prix,即使没有特定月份的记录 –

回答

12

我就不多讲效率,因为我还没有对其他方法,但无需一个临时表这看起来公平的方式去测试它。

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 of both queries.

2

您可能需要一个表来保存每个“月”记录。临时表可以做的伎俩:

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'), ... 

而现在,你可以留下这个新创建的临时表加入您的数据:

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); 

请注意,您可以把临时表创建(并填写)在存储过程中。

为简单起见,我使用last_day,但如果您正确加入,则可以自由使用您喜欢的月份中的任何日期。

希望这有助于

+0

不是一个坏主意,但我认为与几个月的简单结合应该更便宜。 – Prix

+0

@Prix如果用户只需要这么做几个月,我绝对同意你的看法。但是如果用户需要处理很多个月(或几年),那么这种方法很容易出错。此外,可以创建临时表并使用存储过程进行填充,并且可以根据用户需要多次重复使用。 – Barranka