Versión MySQL
El código se ejecutará en MySQL 5.5
Antecedentes
Tengo una mesa como la siguiente
CREATE TABLE t
( id INT NOT NULL AUTO_INCREMENT
, patient_id INT NOT NULL
, bed_id INT NOT NULL
, ward_id INT NOT NULL
, admitted DATETIME NOT NULL
, discharged DATETIME
, PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Esta tabla trata sobre pacientes en un hospital y almacena las camas donde cada paciente pasó algún tiempo mientras estaba hospitalizado.
Cada sala puede tener varias camas y cada paciente puede moverse a una cama diferente dentro de la misma sala.
Objetivo
Lo que quiero hacer es averiguar cuánto tiempo pasó cada paciente en una sala específica sin haberse mudado a una sala diferente. Es decir, quiero encontrar la duración total del tiempo consecutivo que pasó dentro de la misma sala.
Caso de prueba
-- Let's assume that ward_id = 1 corresponds to ICU (Intensive Care Unit)
INSERT INTO t
(patient_id, bed_id, ward_id, admitted, discharged)
VALUES
-- Patient 1 is in ICU, changes some beds, then he is moved
-- out of ICU, back in and finally he is out.
(1, 1, 1, '2015-01-06 06:05:00', '2015-01-07 06:04:00'),
(1, 2, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(1, 1, 1, '2015-01-07 07:08:00', '2015-01-08 08:11:00'),
(1, 4, 2, '2015-01-08 08:11:00', '2015-01-08 09:11:00'),
(1, 1, 1, '2015-01-08 09:11:00', '2015-01-08 10:11:00'),
(1, 3, 1, '2015-01-08 10:11:00', '2015-01-08 11:11:00'),
(1, 1, 2, '2015-01-08 11:11:00', '2015-01-08 12:11:00'),
-- Patient 2 is out of ICU, he gets inserted in ICU,
-- changes some beds and he is back out
(2, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(2, 1, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(2, 3, 1, '2015-01-07 07:08:00', '2015-01-08 08:11:00'),
(2, 1, 2, '2015-01-08 08:11:00', '2015-01-08 09:11:00'),
-- Patient 3 is not inserted in ICU
(3, 1, 2, '2015-01-08 08:10:00', '2015-01-09 09:00:00'),
(3, 2, 2, '2015-01-09 09:00:00', '2015-01-10 10:01:00'),
(3, 3, 2, '2015-01-10 10:01:00', '2015-01-11 12:34:00'),
(3, 4, 2, '2015-01-11 12:34:00', NULL),
-- Patient 4 is out of ICU, he gets inserted in ICU without changing any beds
-- and goes back out.
(4, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(4, 2, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(4, 1, 2, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),
-- Patient 5 is out of ICU, he gets inserted in ICU without changing any beds
-- and he gets dismissed.
(5, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(5, 3, 2, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(5, 1, 1, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),
-- Patient 6 is inserted in ICU and he is still there
(6, 1, 1, '2015-01-11 12:34:00', NULL);
En la tabla real, las filas no son consecutivas, pero para cada paciente la marca de tiempo del alta de una fila == la marca de tiempo de admisión de la siguiente fila.
SQLFiddle
http://sqlfiddle.com/#!2/b5fe5
Resultado Esperado
Me gustaría escribir algo como lo siguiente:
SELECT pid, ward_id, admitted, discharged
FROM (....)
WHERE ward_id = 1;
(1, 1, '2015-01-06 06:05:00', '2015-01-08 08:11:00'),
(1, 1, '2015-01-08 09:11:00', '2015-01-09 11:11:00'),
(2, 1, '2015-01-07 06:04:00', '2015-01-08 08:11:00'),
(4, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(5, 1, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),
(6, 1, '2015-01-11 12:34:00', NULL);
Tenga en cuenta que no podemos agrupar por ID_paciente. Debemos recuperar un registro separado para cada visita a la UCI.
Para decirlo más claramente, si un paciente pasa tiempo en la UCI, luego sale de él y luego regresa allí, necesito recuperar el tiempo total que pasó en cada visita a la UCI (es decir, dos registros)
Respuestas:
Consulta 1, probada en SQLFiddle-1
Consulta 2, que es igual a 1 pero sin las tablas derivadas. Esto probablemente tendrá un mejor plan de ejecución, con índices adecuados. Prueba en SQLFiddle-2 :
Ambas consultas asumen que hay una restricción única en
(patient_id, admitted)
. Si el servidor se ejecuta con una configuración ANSI estricta,bed_id
debe agregarse en laGROUP BY
lista.fuente
CONSULTA PROPUESTA
Cargué sus datos de muestra en una base de datos local en mi computadora portátil. Entonces, ejecuté la consulta
CONSULTA PROPUESTA EJECUTADA
CONSULTA PROPUESTA EXPLICADA
En la subconsulta AA, calculo el número de segundos transcurridos usando UNIX_TIMESTAMP () restando
UNIX_TIMESTAMP(discharged)
FROMUNIX_TIMESTAMP(admitted)
. Si el paciente todavía está en la cama (como lo indica el ser dado de altaNULL
), le asigno la hora actual AHORA () . Entonces, hago la resta. Esto le dará una duración actualizada para cualquier paciente que aún esté en la sala.Luego, agrego la suma de los segundos por
patient_id
. Finalmente, tomo los segundos para cada paciente y uso SEC_TO_TIME () para mostrar las horas, minutos y segundos de la estadía del paciente.DARLE UNA OPORTUNIDAD !!!
fuente
A
yAA
). Creo que uno de ellos es suficiente.