Question

I have a list of timesheet entries that show a start and stop time. This is sitting in a MySQL database. I need to create bar charts based on this data with the 24 hours of the day along the bottom and the amount of man-hours worked for each hour of the day.

For example, if Alice worked a job from 15:30 to 19:30 and Bob worked from 12:15 to 17:00, the chart would look like this:

Example Chart

I have a WTFey solution right now that involves a spreadsheet going out to column DY or something like that. The needed resolution is 15-minute intervals.

I'm assuming this is something best done in the database then exported for chart creation. Let me know if I'm missing any details. Thanks.

Was it helpful?

Solution

Create a table with just time in it from midnight to midnight containing each minute of the day. In the data warehouse world we would call this a time dimension. Here's an example:

TIME_DIM
 -id
 -time_of_day
 -interval_15 
 -interval_30

an example of the data in the table would be

id   time_of_day    interval_15    interval_30
1    00:00          00:00          00:00
...
30   00:23          00:15          00:00
...
100  05:44          05:30          05:30

Then all you have to do is join your table to the time dimension and then group by interval_15. For example:

SELECT b.interval_15, count(*) 
FROM my_data_table a
INNER JOIN time_dim b ON a.time_field = b.time
WHERE a.date_field = now()
GROUP BY b.interval_15

OTHER TIPS

I came up with a pseudocode solution, hope it helps.

create an array named timetable with 24 entries
initialise timetable to zero

for each user in SQLtable
  firsthour = user.firsthour
  lasthour = user.lasthour

  firstminutes = 4 - (rounded down integer(user.firstminutes/15))
  lastminutes = rounded down integer(user.lastminutes/15)

  timetable(firsthour) = timetable(firsthour) + firstminutes
  timetable(lasthour) = timetable(lasthour) + lastminutes

  for index=firsthour+1 to lasthour-1
    timetable(index) = timetable(index) + 4
  next index

next user

Now the timetable array holds the values you desire in 15 minute granularity, ie. a value of 4 = 1 hour, 5 = 1 hour 15 minutes, 14 = 3 hours 30 minutes.

Here's another pseudocode solution from a different angle; a bit more intensive because it does 96 queries for every 24hr period:

results = []
for time in range(0, 24, .25):
  amount = mysql("select count(*) from User_Activity_Table where time >= start_time and time <= end_time")
  results.append(amount)

How about this:

Use that "times" table, but with two columns, containing the 15-minute intervals. The from_times are the 15-minutely times, the to_times are a second before the next from_times. For example 12:30:00 to 12:44:59.

Now get your person work table, which I've called "activity" here, with start_time and end_time columns.

I added values for Alice and Bob as per the original question.

Here's the query from MySQL:

SELECT HOUR(times.from_time) AS 'TIME', count(*) / 4 AS 'HOURS'
FROM times
  JOIN activity
  ON times.from_time >= activity.start_time AND 
     times.to_time   <= activity.end_time
GROUP BY HOUR(times.from_time)
ORDER BY HOUR(times.from_time)

which gives me this:

TIME   HOURS
12     0.7500
13     1.0000
14     1.0000
15     1.5000
16     2.0000
17     1.0000
18     1.0000
19     0.7500

Looks about right...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top