Reputation: 19863
MySQL newbie here. I have these three separate queries. Each one groups by yearweek and selects one additional field.
-- tickets_by_hosts
select
yearweek(r.created_at) as week,
count(zt.id) as tickets_by_hosts
from reservations r
inner join zendesk_tickets zt on zt.reservation_code = r.confirmation_code and zt.requester_id = r.host_id
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
-- tickets_by_guests
select
yearweek(r.created_at) as week,
count(zt.id) as tickets_by_guests
from reservations r
inner join zendesk_tickets zt on zt.reservation_code = r.confirmation_code and zt.requester_id = r.guest_id
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
-- reservations
select
yearweek(r.created_at) as week,
count(r.id) as reservations
from reservations r
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
What is the best way to combine these three queries so the results are all lined up by yearweek like:
week tickets_by_hosts tickets_by_guests reservations
... ... ... ...
Thank you! Have been googling around for this one but no luck so far.
Upvotes: 1
Views: 176
Reputation: 23972
In your case, these do not need to be separate queries. You can implement conditional logic in the aggregate (SUM
, COUNT
etc) function using CASE
.
select
yearweek(r.created_at) as week,
SUM(CASE WHEN zt.requester_id = r.host_id THEN 1 ELSE 0 END ) as tickets_by_hosts,
SUM(CASE WHEN zt.requester_id = r.guest_id THEN 1 ELSE 0 END ) as tickets_by_guests,
COUNT(*) AS reservations,
from reservations r
inner join zendesk_tickets zt
on zt.reservation_code = r.confirmation_code
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
The less efficient approach would be:
SELECT Q1.Week, Q1.Tickets_by_hosts, Q2.Tickets_by_guests, Q3.reservations
FROM (
select
yearweek(r.created_at) as week,
count(zt.id) as tickets_by_hosts
from reservations r
inner join zendesk_tickets zt on zt.reservation_code = r.confirmation_code and zt.requester_id = r.host_id
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
) Q1
INNER JOIN (
select
yearweek(r.created_at) as week,
count(zt.id) as tickets_by_guests
from reservations r
inner join zendesk_tickets zt on zt.reservation_code = r.confirmation_code and zt.requester_id = r.guest_id
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
) Q2
ON Q1.week = Q2.Week
INNER JOIN (
select
yearweek(r.created_at) as week,
count(r.id) as reservations
from reservations r
where
r.created_at > '2011-8-20 00:00:00' and status != 0
group by yearweek(r.created_at)
order by week desc
) Q3
ON Q1.week = Q3.week
For the second example, I rewrote the query to use each of the examples you posted as a subquery (or derived table), then joined them together. In this case, though, the DB would be doing all the work of scanning the tables and calculating the aggregates multiple times, you would also have the work of taking the dynamic result sets and joining them together (because of the nature of these resultsets, you really wouldn't have much benefit from indexes. This second option is the wrong approach, but I include it so you know how to use derived table which may be helpful in the future.
Upvotes: 3