Bạn đang đi đúng hướng, chỉ cần LEFT JOIN
kết quả của truy vấn của bạn đến một bảng tên tháng. Sau đó, các tên tồn tại trong kết quả của bạn sẽ trả về một kết quả khớp và NULL
sẽ được trả lại cho những tháng không có trong kết quả của bạn. COALESCE
hoặc NVL
hoặc CASE
cấu trúc, bất cứ điều gì bạn thích, có thể được sử dụng để biến NULL
đó thành một 0
.
Bạn không cần tạo một bảng tháng thực sự, bạn có thể có được bằng cách sử dụng chế độ xem nội tuyến - chỉ đơn giản là một truy vấn tạo ra tất cả dữ liệu tháng.
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
Đối với việc trả lại mọi thông tin trong một năm cụ thể, hãy xem điều kiện WHERE. Tôi đang coi appt_date_time là ngày giờ hoặc dấu thời gian. Bạn không muốn viết YEAR (appt_date_time) =2012 vì điều đó sẽ làm hỏng cơ hội sử dụng chỉ mục trên cột đó (tôi giả sử cột đó xuất hiện dưới dạng cột đầu tiên trong chỉ mục). Bằng cách sử dụng GIỮA ... VÀ và so sánh với lịch ngày theo nghĩa đen, bạn có thể có một truy vấn khá hiệu quả đáp ứng yêu cầu.
Ngoài ra, nếu bạn GROUP BY
vào month(appt_date_time)
mysql sẽ đảm bảo kết quả cũng sẽ được sắp xếp tăng dần theo tháng. Vì vậy, không cần một ORDER BY
riêng biệt . Thứ tự của 'chân' của truy vấn UNION cũng sẽ được mysql giữ nguyên.