Estás en el camino correcto, solo LEFT JOIN
el resultado de su consulta a una tabla de nombres de meses. Luego, los nombres que existen en su resultado devolverán una coincidencia y un NULL
será devuelto por aquellos meses que no están en su resultado. UN COALESCE
o NVL
o CASE
La construcción, lo que quieras, se puede usar para convertir eso NULL
en un 0
recto .
No necesita hacer una tabla real de meses, puede obtenerla usando una vista en línea, simplemente una consulta que genera todos los datos del mes.
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 cuanto a devolver todo para un año en particular, mire la condición DONDE. Supongo que appt_date_time es una fecha y hora o una marca de tiempo. No desea escribir AÑO (appt_date_time) =2012 porque eso arruinará las posibilidades de usar un índice en esa columna (supongo que esa columna aparece como la primera columna en un índice). Al usar BETWEEN... AND y comparar con fechas y horas literales, puede tener una consulta bastante eficiente que cumpla con el requisito.
Además, si GROUP BY
el month(appt_date_time)
mysql se asegurará de que los resultados también se ordenen de forma ascendente por mes. Así que no hay necesidad de un ORDER BY
separado . mysql también conservará el orden de los 'tramos' de la consulta UNION.