Anda perlu membuat semua tanggal yang diinginkan, dan kemudian bergabung dengan data Anda ke tanggal. Perhatikan juga bahwa penting untuk meletakkan beberapa predikat di kiri gabungan ON
klausa, dan lainnya di WHERE
klausa:
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
Bagaimana cara kerja di atas?
CROSS JOIN
membuat produk kartesius antara semua tahun yang tersedia dan semua bulan yang tersedia. Inilah yang Anda inginkan, Anda ingin semua kombinasi tahun-bulan tanpa jeda.LEFT JOIN
menambahkan semuaqualitaet
mencatat hasil (jika ada) dan menggabungkannya ke produk kartesius tahun-bulan dari sebelumnya. Penting untuk menempatkan predikat sepertistatus = 1
predikat di sini.COUNT(created)
hanya menghitung nilai non-NULL daricreated
, yaitu ketikaLEFT JOIN
tidak menghasilkan baris untuk tahun-bulan tertentu, kami ingin0
sebagai hasilnya, bukan1
, yaitu kita tidak ingin menghitungNULL
nilai.
Catatan tentang performa
Di atas banyak menggunakan operasi string dan aritmatika waktu tanggal di ON
. Anda dan WHERE
predikat. Ini tidak akan berfungsi untuk banyak data. Dalam hal ini, sebaiknya Anda melakukan pra-pemotongan dan mengindeks tahun-bulan Anda di qualitaet
tabel, dan hanya beroperasi pada nilai tersebut.