Vous êtes sur la bonne voie, il vous suffit de LEFT JOIN
le résultat de votre requête à une table de noms de mois. Ensuite, les noms qui existent dans votre résultat renverront une correspondance et un NULL
sera retourné pour les mois qui ne figurent pas dans votre résultat. Un COALESCE
ou NVL
ou CASE
la construction, comme vous voulez, peut être utilisée pour transformer ce NULL
en un 0
droit .
Vous n'avez pas besoin de créer une vraie table de mois, vous pouvez l'obtenir en utilisant une vue en ligne - simplement une requête qui génère toutes les données du mois.
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
En ce qui concerne le retour de tout pour une année particulière, regardez la condition WHERE. Je suppose que appt_date_time est une date/heure ou un horodatage. Vous ne voulez pas écrire YEAR(appt_date_time) =2012 car cela ruinerait les chances d'utiliser un index sur cette colonne (je suppose que cette colonne apparaît comme la première colonne d'un index). En utilisant un BETWEEN... AND et en comparant avec des datetimes littérales, vous pouvez avoir une requête assez efficace qui répond à l'exigence.
Aussi, si vous GROUP BY
le month(appt_date_time)
mysql s'assurera que les résultats seront également triés par mois. Donc pas besoin d'un ORDER BY
séparé . L'ordre des 'jambes' de la requête UNION sera également préservé par mysql.