Du måste generera alla önskade datum och sedan lämna din data till datumen. Observera också att det är viktigt att sätta några predikat i vänster joins ON sats och andra i WHERE klausul:
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
Hur fungerar ovanstående?
CROSS JOINskapar en kartesisk produkt mellan alla tillgängliga år och alla tillgängliga månader. Det här är vad du vill, du vill ha kombinationer hela året och månaden utan luckor.LEFT JOINlägger till allaqualitaetposter till resultatet (om de finns) och sammanfogar dem med den kartesiska årsprodukten från tidigare. Det är viktigt att sätta prediakter somstatus = 1predikat här.COUNT(created)räknar endast icke-NULL-värden förcreated, dvs närLEFT JOINproducerar inga rader för en given år-månad, vi vill ha0som ett resultat, inte1, det vill säga vi vill inte räknaNULLvärde.
En notering om prestanda
Ovanstående använder mycket strängoperationer och aritmetik för datum och tid i din ON och WHERE predikat. Detta kommer inte att fungera för mycket data. I så fall bör du bättre förkorta och indexera dina årsmånader i qualitaet tabell och arbeta endast på dessa värden.