Version MySQL
Le code s'exécutera dans MySQL 5.5
Contexte
J'ai une table comme la suivante
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;
Ce tableau concerne les patients d'un hôpital et il stocke les lits où chaque patient a passé un certain temps pendant son hospitalisation.
Chaque salle peut avoir plusieurs lits et chaque patient peut se déplacer vers un lit différent dans la même salle.
Objectif
Ce que je veux faire, c'est trouver combien de temps chaque patient a passé dans une salle spécifique sans avoir déménagé dans une autre salle. C'est-à-dire que je veux trouver la durée totale du temps consécutif qu'il a passé dans la même salle.
Cas de test
-- 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);
Dans le tableau réel, les lignes ne sont pas consécutives, mais pour chaque patient, l'horodatage de sortie d'une ligne == l'horodatage d'admission de la ligne suivante.
SQLFiddle
http://sqlfiddle.com/#!2/b5fe5
résultat attendu
Je voudrais écrire quelque chose comme ceci:
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);
Veuillez noter que nous ne pouvons pas regrouper par patient_id. Nous devons récupérer un dossier distinct pour chaque visite aux soins intensifs.
Pour le dire plus clairement, si un patient passe du temps à l'USI, puis en sort et y retourne, j'ai besoin de récupérer le temps total qu'il a passé à chaque visite en USI (c.-à-d. Deux enregistrements)
Réponses:
Requête 1, testée dans SQLFiddle-1
Requête 2, qui est identique à 1 mais sans les tables dérivées. Cela aura probablement un meilleur plan d'exécution, avec des index appropriés. Test dans SQLFiddle-2 :
Les deux requêtes supposent qu'il existe une contrainte unique sur
(patient_id, admitted)
. Si le serveur fonctionne avec des paramètres ANSI stricts, lebed_id
doit être ajouté dans laGROUP BY
liste.la source
DEMANDE PROPOSÉE
Je vous ai chargé des échantillons de données dans une base de données locale sur mon ordinateur portable. Ensuite, j'ai exécuté la requête
REQUÊTE PROPOSÉE EXÉCUTÉE
REQUÊTE PROPOSÉE EXPLIQUÉE
Dans la sous-requête AA, je calcule le nombre de secondes écoulées à l'aide d' UNIX_TIMESTAMP () en soustrayant
UNIX_TIMESTAMP(discharged)
FROMUNIX_TIMESTAMP(admitted)
. Si le patient est toujours dans le lit (comme indiqué par le congéNULL
), j'attribue l'heure actuelle MAINTENANT () . Ensuite, je fais la soustraction. Cela vous donnera une durée à la minute pour tout patient encore dans la salle.Ensuite, j'agrège la somme des secondes par
patient_id
. Enfin, je prends les secondes pour chaque patient et j'utilise SEC_TO_TIME () pour afficher les heures, les minutes et les secondes du séjour du patient.ESSAIE !!!
la source
A
etAA
). Je pense que l'un d'eux suffit.