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 JOIN
skapar 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 JOIN
lägger till allaqualitaet
poster till resultatet (om de finns) och sammanfogar dem med den kartesiska årsprodukten från tidigare. Det är viktigt att sätta prediakter somstatus = 1
predikat här.COUNT(created)
räknar endast icke-NULL-värden förcreated
, dvs närLEFT JOIN
producerar inga rader för en given år-månad, vi vill ha0
som ett resultat, inte1
, det vill säga vi vill inte räknaNULL
vä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.