Wersja MySQL
Kod będzie działał w MySQL 5.5
tło
Mam tabelę podobną do poniższej
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;
Ta tabela dotyczy pacjentów w szpitalu i zawiera łóżka, na których każdy pacjent spędził trochę czasu podczas hospitalizacji.
Każdy oddział może mieć wiele łóżek, a każdy pacjent może przenieść się do innego łóżka w tym samym oddziale.
Cel
Chcę ustalić, ile czasu każdy pacjent spędził na określonym oddziale, nie przeprowadzając się na inny oddział. Tj. Chcę znaleźć całkowity czas z rzędu, jaki spędził w obrębie tego samego totemu.
Przypadek testowy
-- 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);
W prawdziwej tabeli wiersze nie są następujące po sobie, ale dla każdego pacjenta znacznik czasu wypisu z jednego rzędu == znacznik czasu przyjęcia następnego rzędu.
SQLFiddle
http://sqlfiddle.com/#!2/b5fe5
Spodziewany wynik
Chciałbym napisać coś takiego:
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);
Proszę pamiętać, że nie możemy grupować według ID_ pacjenta. Musimy pobrać osobny rekord dla każdej wizyty na OIOM.
Mówiąc prościej, jeśli pacjent spędza czas na OIOM, następnie się z niego wyprowadza, a następnie wraca z powrotem, muszę odzyskać całkowity czas spędzony podczas każdej wizyty na OIOM (tj. Dwa zapisy)
Odpowiedzi:
Zapytanie 1, przetestowane w SQLFiddle-1
Zapytanie 2, które jest takie samo jak 1, ale bez pochodnych tabel. Zapewne będzie to miał lepszy plan wykonania z odpowiednimi indeksami. Test w SQLFiddle-2 :
Oba zapytania zakładają, że istnieje wyjątkowe ograniczenie
(patient_id, admitted)
. Jeśli serwer działa ze ścisłymi ustawieniami ANSI,bed_id
należy go dodać naGROUP BY
liście.źródło
PROPONOWANE ZAPYTANIE
Załadowałem ci przykładowe dane do lokalnej bazy danych na moim laptopie. Następnie uruchomiłem zapytanie
PROPONOWANE WYKONANE ZAPYTANIE
PROPONOWANE WYJAŚNIENIE
W podzapytaniu AA obliczam liczbę sekund, które upłynęły za pomocą UNIX_TIMESTAMP () , odejmując
UNIX_TIMESTAMP(discharged)
FROMUNIX_TIMESTAMP(admitted)
. Jeśli pacjent nadal leży w łóżku (jak wskazuje na toNULL
, że jest wypisany ), przypisuję bieżący czas TERAZ () . Następnie odejmuję. To da ci maksymalny czas trwania dla każdego pacjenta nadal na oddziale.Następnie sumuję sekundy według
patient_id
. Na koniec pobieram sekundy dla każdego pacjenta i używam SEC_TO_TIME () do wyświetlania godzin, minut i sekund pozostawania pacjenta.SPRÓBUJ !!!
źródło
A
iAA
). Myślę, że jeden z nich wystarczy.