Sie sind auf dem richtigen Weg, LEFT JOIN
das Ergebnis Ihrer Abfrage in eine Tabelle mit Monatsnamen. Dann geben die in Ihrem Ergebnis vorhandenen Namen eine Übereinstimmung und einen NULL
zurück werden für die Monate zurückgegeben, die nicht in Ihrem Ergebnis enthalten sind. Ein COALESCE
oder NVL
oder CASE
Konstrukt, was immer Sie wollen, kann verwendet werden, um diesen NULL
zu machen in eine gerade 0
.
Sie müssen keine echte Monatstabelle erstellen, Sie können eine Inline-Ansicht verwenden - einfach eine Abfrage, die alle Monatsdaten generiert.
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
Um alles für ein bestimmtes Jahr zurückzugeben, sehen Sie sich die WHERE-Bedingung an. Ich gehe davon aus, dass appt_date_time eine Datetime oder ein Timestamp ist. Sie möchten nicht YEAR(appt_date_time) =2012 schreiben, da dies die Chancen ruiniert, einen Index für diese Spalte zu verwenden (ich gehe davon aus, dass diese Spalte als erste Spalte in einem Index erscheint). Indem Sie ein BETWEEN...AND verwenden und mit wörtlichen Datums- und Uhrzeitangaben vergleichen, können Sie eine ziemlich effiziente Abfrage haben, die die Anforderung erfüllt.
Auch, wenn Sie GROUP BY
verwenden am month(appt_date_time)
mysql stellt sicher, dass die Ergebnisse auch nach Monat aufsteigend sortiert werden. Es ist also kein separater ORDER BY
erforderlich . Die Reihenfolge der 'Zweige' der UNION-Abfrage wird auch von mysql beibehalten.