Solución
Base de datos
EstrategÃa 1: Transformar los valores usando CASE WHEN y hacer el cálculo
Algoritmo
Para calcular el tiempo para completar un proceso, necesitamos conocer la diferencia entre el tiempo de inicio y el tiempo de finalización de cada máquina y proceso. Si negamos el tiempo de inicio, podemos obtener la diferencia de tiempo usando SUM()
, dado que (-start) + end
es igual a end - start
, lo cuál indica la diferencia de tiempo.
Para hacer esto, usamos CASE WHEN
para multiplicar todos los tiempos de inicio por -1
, asi que el total de tiempo se convierte en el tiempo para completar el proceso para cada máquina.
SUM(
CASE WHEN activity_type = 'start' THEN
timestamp*-1
ELSE
timestamp
END
)
Dado que necesitamos el promedio por cada machine_id
y podrÃa haber múltiples procesos ejecutándose en cada máquina, manualmente calculamos el promedio dividiendo el tiempo del proceso entre el número de procesos. Afortunadamente, para esta pregunta, todas las máquinas tienen el mismo número de procesos.
SUM(
CASE WHEN activity_type='start' THEN
timestamp*-1
ELSE
timestamp
END
) * 1.0 / (SELECT COUNT(DISTINCT process_id))
Por último, redondeamos el processing_time
a 3 decimales con la función ROUND()
y renombramos la columna.
ROUND(
SUM(
CASE WHEN activity_type='start' THEN
timestamp*-1
ELSE
timestamp END
) * 1.0 / (SELECT COUNT(DISTINCT process_id)), 3
) AS processing_time
Implementación
SELECT
machine_id,
ROUND(
SUM(
CASE WHEN activity_type='start' THEN
timestamp*-1
ELSE
timestamp END
) * 1.0 / (SELECT COUNT(DISTINCT process_id)), 3
) AS processing_time
FROM
Activity
GROUP BY machine_id
EstrategÃa 2: Usar la tabla original dos veces y calcular como si fueran dos columnas
Algoritmo
Para este método, usamos la tabla dos veces, una vez como la tabla que tiene el tiempo de inicio y otra como la tabla que tiene el tiempo de finalización. Para crear ambos aliases, le asignamos diferentes nombres, y filtramos cada tabla por activity_type
. También nos aseguramos de que las dos tablas sea unidas a través de su machine_id
y process_id
, de manera que el resultado tendrá el tiempo de inicio y tiempo de finalización en dos columnas diferentes para cada máquina y proceso.
SELECT *
FROM Activity a,
Activity b
WHERE
a.machine_id = b.machine_id
AND
a.process_id = b.process_id
AND
a.activity_type = 'start'
AND
b.activity_type = 'end'
Un ejemplo de la salida se muenstra enseguida:
machine_id | process_id | activity_type | timestamp | machine_id | process_id | activity_type | timestamp |
---|---|---|---|---|---|---|---|
0 | 0 | start | 0.712 | 0 | 0 | end | 1.52 |
0 | 1 | start | 3.14 | 0 | 1 | end | 4.12 |
1 | 0 | start | 0.55 | 1 | 0 | end | 1.55 |
1 | 1 | start | 0.43 | 1 | 1 | end | 1.42 |
2 | 0 | start | 4.1 | 2 | 0 | end | 4.512 |
2 | 1 | start | 2.5 | 2 | 1 | end | 5 |
Con esta tabla, podemos actualizar el cálculo de processing_time
substrayendo los timestamps de la tabla b
con los de la tabla a:
SELECT (
b.timestamp - a.timestamp
) AS processing_time
Dado que queremos el promedio de processing_time
por cada máquina, agregamos AVG()
al cálculo de
processing_time
y redondeamos a 3 decimales usando la función ROUND()
.
SELECT a.machine_id,
ROUND(AVG(b.timestamp - a.timestamp), 3) AS processing_time
Implementation
SELECT a.machine_id,
ROUND(
AVG(b.timestamp - a.timestamp),
3
) AS processing_time
FROM Activity a,
Activity b
WHERE
a.machine_id = b.machine_id
AND
a.process_id = b.process_id
AND
a.activity_type = 'start'
AND
b.activity_type = 'end'
GROUP BY machine_id