选择出现次数为零的每月计数

Selecting monthly counts with zero occurrences

我的问题是根据 creatin 的年份和月份从数据库中选择记录计数。我有这个 MySQL 查询:

SELECT year, m, month, COUNT(bans.ban_id) AS total
FROM (
    SELECT year, m, month
    FROM
    (SELECT YEAR(CURDATE()) year UNION ALL SELECT YEAR(CURDATE())-1) years,
    (
        SELECT 1 m, 'Jan' month
        UNION ALL SELECT 2 m, 'Feb' month
        UNION ALL SELECT 3 m, 'Mar' month
        UNION ALL SELECT 4 m, 'Apr' month
        UNION ALL SELECT 5 m, 'May' month
        UNION ALL SELECT 6 m, 'Jun' month
        UNION ALL SELECT 7 m, 'Jul' month
        UNION ALL SELECT 8 m, 'Aug' month
        UNION ALL SELECT 9 m, 'Sep' month
        UNION ALL SELECT 10 m, 'Oct' month
        UNION ALL SELECT 11 m, 'Nov' month
        UNION ALL SELECT 12 m, 'Dec' month
    ) months
) ym
LEFT JOIN bans
    ON ym.year = YEAR(bans.ban_created_at)
    AND ym.m = MONTH(bans.ban_created_at)
WHERE
    (year=YEAR(CURDATE()) AND m<=MONTH(CURDATE()))
    OR
    (year<YEAR(CURDATE()) AND m>MONTH(CURDATE()))
    AND
    (ban_banlist_id = 13)
GROUP BY year, m

它几乎可以正常工作,但是 - 问题是查询 returns 仅具有有效记录数的值 - 例如当月没有记录时,不返回

原因是右边的条件table(bans)在WHERE子句上,所以它作用在结果上,效果是只有出现的月份才会被选中。放在LEFT JOIN子句的ON子句上,像这样:

SELECT year, m, month, COUNT(bans.ban_id) AS total
FROM (
    SELECT year, m, month
    FROM
    (SELECT YEAR(CURDATE()) year UNION ALL SELECT YEAR(CURDATE())-1) years,
    (
        SELECT 1 m, 'Jan' month
        UNION ALL SELECT 2 m, 'Feb' month
        UNION ALL SELECT 3 m, 'Mar' month
        UNION ALL SELECT 4 m, 'Apr' month
        UNION ALL SELECT 5 m, 'May' month
        UNION ALL SELECT 6 m, 'Jun' month
        UNION ALL SELECT 7 m, 'Jul' month
        UNION ALL SELECT 8 m, 'Aug' month
        UNION ALL SELECT 9 m, 'Sep' month
        UNION ALL SELECT 10 m, 'Oct' month
        UNION ALL SELECT 11 m, 'Nov' month
        UNION ALL SELECT 12 m, 'Dec' month
    ) months
) ym
LEFT JOIN bans
    ON ym.year = YEAR(bans.ban_created_at)
    AND ym.m = MONTH(bans.ban_created_at)
    AND ban_banlist_id = 13
WHERE
    (year=YEAR(CURDATE()) AND m<=MONTH(CURDATE()))
    OR
    (year<YEAR(CURDATE()) AND m>MONTH(CURDATE()))
GROUP BY year, m