I have been asked to put together a small reporting system at work. We have a database where users commit information, namely a start and a stop time for various events.
The relevant tables of the DB:
As you can see, an event has a subcategory, and each subcategory belongs to a category.
I have been asked to produce a graph that represents the total amount of time events of a given category have occurred in a given date range.
So for example:
Category Name | Total time
**************************
Balloons | 12h
Chalk | 5.5h
I am struggling with getting a sum out of a join statement. As you can see, in order to map the total amounts of time to various categories, I have to first identify which subcategories belong to which categories, then organize the events accordingly.
I admit, I have been dead-set on writing this in one single query instead of writing a stored procedure or create temporary tables. I was convinced I could get it done with only joins, but it does not seem to be the case. I am completely open to any solution that works
One requirement; If a given category has no events, it should still appear in the results, only with a default value of 0.
This is what I have so far:
SELECT
event_categories.name,
SUM(TIMESTAMPDIFF(MINUTE,
events.start,
events.stop) / 60) AS timeLost
FROM
events
LEFT JOIN
event_subcategories ON event_subcategories.id = events.subcategory
RIGHT JOIN
event_categories ON event_categories.id = event_subcategories.id
WHERE
events.date BETWEEN '2016-12-01' AND '2016-12-22'
AND events.bed = 1
GROUP BY event_categories.id;
It almost works, producing a list of categories with the associated time lost. Only it doesn't display all of the categories, just the ones with events associated to them.
Change the way you do the joins. The main table should be event_categories
. Assuming every category has subcategories, you can then use INNER JOIN
with event_subcategories
. Finally use LEFT JOIN
with events
, since some subcategories might not have any events.
You were also joining event_categories
and event_subcategories
on the wrong columns. It should be event_subcategories.category
, not event_subcategory.id
.
When you do a LEFT JOIN
, any conditions on the child table should be in the ON
clause, not WHERE
. Because any category with no events will get NULL
for all the event
columns, so the conditions will never succeed for those rows and they would get filtered out as if you were doing INNER JOIN
.
SELECT
c.name,
SUM(TIMESTAMPDIFF(MINUTE,
e.start,
e.stop) / 60) AS timeLost
FROM event_categories AS c
JOIN event_subcategories AS s ON s.category = c.id
LEFT JOIN events AS e ON e.subcategory = s.id
AND e.date BETWEEN '2016-12-01' AND '2016-12-22'
AND e.bed = 1
GROUP BY c.id;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.