Вие сте на прав път, просто LEFT JOIN
резултатът от вашата заявка към таблица с имена на месеци. Тогава имената, които съществуват във вашия резултат, ще върнат съвпадение и NULL
ще бъдат върнати за тези месеци, които не са във вашия резултат. A COALESCE
или NVL
или CASE
construct, каквото пожелаете, може да се използва за превръщане на това NULL
в прав 0
.
Не е необходимо да правите реална таблица с месеци, можете да получите с помощта на вграден изглед - просто заявка, която генерира всички данни за месеца.
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
Що се отнася до връщането на всичко за конкретна година, вижте условието WHERE. Предполагам, че appt_date_time е дата и час. Не искате да пишете YEAR(appt_date_time) =2012, защото това ще разруши шансовете за използване на индекс в тази колона (предполагам, че тази колона се появява като първа колона в индекс). Като използвате МЕЖДУ...И и сравнявате с буквални дати и времена, можете да имате доста ефективна заявка, която отговаря на изискването.
Също така, ако GROUP BY
на month(appt_date_time)
mysql ще гарантира, че резултатите ще бъдат сортирани и по месеци. Така че няма нужда от отделен ORDER BY
. Редът на „краката“ на заявката UNION също ще бъде запазен от mysql.