必要なすべての日付を生成してから、データを日付に結合したままにする必要があります。左側の結合のON
にいくつかの述語を入れることが重要であることにも注意してください。 WHERE
の句など 条項:
SELECT
CONCAT(y, '-', LPAD(m, 2, '0')) as byMonth,
COUNT(`created`) AS Total
FROM (
SELECT year(now()) AS y UNION ALL
SELECT year(now()) - 1 AS y
) `years`
CROSS JOIN (
SELECT 1 AS m UNION ALL
SELECT 2 AS m UNION ALL
SELECT 3 AS m UNION ALL
SELECT 4 AS m UNION ALL
SELECT 5 AS m UNION ALL
SELECT 6 AS m UNION ALL
SELECT 7 AS m UNION ALL
SELECT 8 AS m UNION ALL
SELECT 9 AS m UNION ALL
SELECT 10 AS m UNION ALL
SELECT 11 AS m UNION ALL
SELECT 12 AS m
) `months`
LEFT JOIN `qualitaet` q
ON YEAR(`created`) = y
AND MONTH(`created`) = m
AND `status` = 1
WHERE STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d')
>= MAKEDATE(year(now()-interval 1 year),1) + interval 5 month
AND STR_TO_DATE(CONCAT(y, '-', m, '-01'), '%Y-%m-%d')
<= now()
GROUP BY y, m
ORDER BY y, m
上記はどのように機能しますか?
-
CROSS JOIN
デカルト積 を作成します 利用可能なすべての年と利用可能なすべての月の間。これはあなたが望むものであり、ギャップのないすべての年月の組み合わせが必要です。 -
LEFT JOIN
すべてのqualitaet
を追加します 結果を記録し(存在する場合)、前からの年月のデカルト積に結合します。status = 1
のようなprediactsを配置することが重要です ここに述語があります。 -
COUNT(created)
created
のNULL以外の値のみをカウントします 、つまり、LEFT JOIN
特定の年月に行を生成しないため、0
が必要です 結果として、1
ではありません 、つまり、NULL
をカウントしたくない 値。
パフォーマンスに関する注意
上記は、ON
で文字列演算と日時演算を多用しています。 およびWHERE
述語。これは、大量のデータに対しては機能しません。その場合は、qualitaet
で年月を事前に切り捨てて、インデックスを作成することをお勧めします。 テーブルを作成し、それらの値のみを操作します。