Método elegante para desenhar um gráfico de barras horárias a partir de dados de intervalo de tempo?

StackOverflow https://stackoverflow.com/questions/79789

  •  09-06-2019
  •  | 
  •  

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:

Example Chart

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.

Foi útil?

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...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top