Du er på rette vej, bare LEFT JOIN
resultatet af din forespørgsel til en tabel med månedsnavne. Så vil de navne, der findes i dit resultat, returnere et match og en NULL
vil blive returneret for de måneder, der ikke er i dit resultat. En COALESCE
eller NVL
eller CASE
konstruktion, hvad end du vil, kan bruges til at vende den NULL
ind i en lige 0
.
Du behøver ikke lave en rigtig tabel over måneder, du kan få ved at bruge en indlejret visning - simpelthen en forespørgsel, der genererer alle månedsdata.
select months.month, coalesce(appts.monthly_total, 0) monthly_total
from (
select 'January' as month
union all select 'February'
union all select 'March'
...etc...
union all select 'December'
) months
left join (
select sum(service_price) as monthly_total,
monthname(appt_date_time) as month
from appt_tbl
inner join services_tbl
on appt_tbl.service_id = services_tbl.service_id
where appt_date_time between '2012-01-01 00:00:00'
and '2012-12-31 23:59:59'
group by month(appt_date_time)
) appts
on months.month = appts.month
Med hensyn til returnering af alt for et bestemt år, se på WHERE-tilstanden. Jeg antager, at appt_date_time er et datetime eller tidsstempel. Du ønsker ikke at skrive YEAR(appt_date_time) =2012, fordi det vil ødelægge chancerne for at bruge et indeks på den kolonne (jeg antager, at kolonnen vises som en første kolonne i et indeks). Ved at bruge et BETWEEN...AND og sammenligne med bogstavelige datotider, kan du få en ret effektiv forespørgsel, der opfylder kravet.
Også, hvis du GROUP BY
på month(appt_date_time)
mysql vil sikre, at resultaterne også sorteres stigende efter måned. Så der er ikke behov for en separat ORDER BY
. Rækkefølgen af "benene" af UNION-forespørgslen vil også blive bevaret af mysql.