Versão do MySQL
O código será executado no MySQL 5.5
fundo
Eu tenho uma tabela como a seguinte
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 tabela é sobre pacientes em um hospital e armazena as camas em que cada paciente passou algum tempo enquanto estava hospitalizado.
Cada ala pode ter várias camas e cada paciente pode se mudar para uma cama diferente dentro da mesma ala.
Objetivo
O que eu quero fazer é descobrir quanto tempo cada paciente passou em uma ala específica sem ter se mudado para uma ala diferente. Ou seja, quero descobrir a duração total do tempo consecutivo que ele passou na mesma ala.
Caso de teste
-- 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);
Na tabela real, as linhas não são consecutivas, mas para cada paciente o registro de data e hora de alta de uma linha == o registro de data e hora de admissão da próxima linha.
SQLFiddle
http://sqlfiddle.com/#!2/b5fe5
resultado esperado
Eu gostaria de escrever algo como o seguinte:
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);
Por favor, observe que não podemos agrupar por Patient_id. Devemos recuperar um registro separado para cada visita à UTI.
Em outras palavras, se um paciente passa um tempo na UTI, depois se muda e volta para lá, preciso recuperar o tempo total que ele passou em cada visita à UTI (ou seja, dois registros)
Respostas:
Consulta 1, testada no SQLFiddle-1
Consulta 2, que é igual a 1, mas sem as tabelas derivadas. Provavelmente, este terá um melhor plano de execução, com índices adequados. Teste no SQLFiddle-2 :
Ambas as consultas assumem que existe uma restrição exclusiva
(patient_id, admitted)
. Se o servidor for executado com configurações ANSI estritas, elebed_id
deverá ser adicionado naGROUP BY
lista.fonte
CONSULTA PROPOSTA
Carreguei seus dados de amostra em um banco de dados local no meu laptop. Então, eu executei a consulta
CONSULTA PROPOSTA EXECUTADA
CONSULTA PROPOSTA EXPLICADA
Na subconsulta AA, calculo o número de segundos decorridos usando UNIX_TIMESTAMP () subtraindo
UNIX_TIMESTAMP(discharged)
FROMUNIX_TIMESTAMP(admitted)
. Se o paciente ainda estiver na cama (como indicado por altaNULL
), atribuo a hora atual NOW () . Então, eu faço a subtração. Isso fornecerá uma duração atualizada para qualquer paciente ainda na enfermaria.Então, agrego a soma dos segundos por
patient_id
. Por fim, tomo os segundos para cada paciente e uso SEC_TO_TIME () para exibir horas, minutos e segundos da permanência do paciente.DE UMA CHANCE !!!
fonte
A
eAA
). Eu acho que um deles é suficiente.