Método elegante para desenhar um gráfico de barras horárias a partir de dados de intervalo de tempo?
Pergunta
Eu tenho uma lista de entradas do quadro de horários que mostram um horário de início e término.Isso está em um banco de dados MySQL.Preciso criar gráficos de barras com base nesses dados com as 24 horas do dia na parte inferior e a quantidade de horas-homem trabalhadas para cada hora do dia.
Por exemplo, se Alice trabalhasse das 15h30 às 19h30 e Bob trabalhasse das 12h15 às 17h, o gráfico ficaria assim:
Eu tenho uma solução WTFey agora que envolve uma planilha indo para a coluna DY ou algo parecido.A resolução necessária é de intervalos de 15 minutos.
Presumo que isso seja algo melhor feito no banco de dados e depois exportado para criação de gráficos.Deixe-me saber se estou faltando algum detalhe.Obrigado.
Solução
Crie uma tabela com apenas o horário da meia-noite à meia-noite contendo cada minuto do dia.No mundo do data warehouse, chamaríamos isso de dimensão de tempo.Aqui está um exemplo:
TIME_DIM
-id
-time_of_day
-interval_15
-interval_30
um exemplo dos dados da tabela seria
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
Então tudo que você precisa fazer é unir sua tabela à dimensão de tempo e agrupar por interval_15.Por exemplo:
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
Outras dicas
Eu criei uma solução em pseudocódigo, espero que ajude.
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
Agora, a matriz de horários contém os valores desejados com granularidade de 15 minutos, ou seja.um valor de 4 = 1 hora, 5 = 1 hora e 15 minutos, 14 = 3 horas e 30 minutos.
Aqui está outra solução de pseudocódigo de um ângulo diferente;um pouco mais intensivo porque faz 96 consultas a cada período de 24 horas:
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)
Que tal agora:
Use aquela tabela de “tempos”, mas com duas colunas, contendo os intervalos de 15 minutos.Os from_times são os tempos de 15 minutos, os to_times são um segundo antes do próximo from_times.Por exemplo, das 12h30 às 12h44:59.
Agora pegue sua tabela de trabalho pessoal, que chamei de "atividade" aqui, com colunas start_time e end_time.
Adicionei valores para Alice e Bob conforme a pergunta original.
Aqui está a consulta do 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)
o que me dá isso:
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
Parece certo...