Jesteś na dobrej drodze, po prostu LEFT JOIN
wynik zapytania do tabeli nazw miesięcy. Następnie nazwy istniejące w wyniku zwrócą dopasowanie, a NULL
zostanie zwrócony za te miesiące, które nie są w twoim wyniku. COALESCE
lub NVL
lub CASE
konstrukcja, cokolwiek chcesz, może być użyta do zmiany tego NULL
do prostego 0
.
Nie musisz tworzyć prawdziwej tabeli miesięcy, możesz ją uzyskać za pomocą widoku wbudowanego - po prostu zapytanie, które generuje wszystkie dane miesięczne.
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
Jeśli chodzi o zwrot wszystkiego za dany rok, spójrz na stan WHERE. Zakładam, że appt_date_time to data i godzina lub znacznik czasu. Nie chcesz pisać YEAR(appt_date_time) =2012, ponieważ zrujnuje to szanse na użycie indeksu w tej kolumnie (zakładam, że ta kolumna pojawia się jako pierwsza kolumna w indeksie). Używając BETWEEN...AND i porównując z dosłownymi datami i godzinami, możesz uzyskać całkiem wydajne zapytanie, które spełnia wymagania.
Również, jeśli GROUP BY
w month(appt_date_time)
mysql zapewni, że wyniki zostaną posortowane rosnąco według miesiąca. Więc nie ma potrzeby oddzielnego ORDER BY
. Kolejność „nóg” zapytania UNION zostanie również zachowana przez mysql.