即使数据不存在,Mysql也可以选择逐月记录

时间:2013-07-29 04:57:05

标签: 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
--------------------------

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

2 个答案:

答案 0 :(得分: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.

答案 1 :(得分: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,但如果您正确加入,则可以自由使用您喜欢的月份中的任何日期。

希望这有帮助