Трябва да генерирате всички желани дати и след това ляво да присъедините данните си към датите. Имайте предвид също, че е важно да поставите някои предикати в 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
предикат тук.COUNT(created)
отчита само стойности, различни от NULL наcreated
, т.е. когатоLEFT JOIN
не произвежда редове за дадена година-месец, искаме0
в резултат на това не1
, т.е. не искаме да броимNULL
стойност.
Бележка за производителността
Горното използва силно операциите с низове и аритметиката за дата и час във вашия ON
и WHERE
предикати. Това няма да работи за много данни. В такъв случай трябва по-добре предварително да съкратите и индексирате своите години-месеци в qualitaet
таблица и оперирайте само с тези стойности.