Przykłady / System szpitalny
System szpitalny
Baza danych szpitala kręci się wokół dwóch tabel zdarzeń. Wizyta to ambulatoryjna wizyta u lekarza, a hospitalizacja to pobyt na oddziale. Obie tabele odwołują się do pacjenta. Recepty wystawia się przy wizycie i odwołują się one do katalogu leków.
Poniżej ErdDocs rysuje ten schemat z jego SQL, ze wszystkimi tabelami i relacjami. W karcie „Słownik danych” znajdziesz wersję do druku, w całości i za darmo na tej stronie. SQL jest jeszcze niżej.
Najedź na tabelę, żeby podświetlić jej relacje, i kliknij, żeby je przypiąć.
Do czego służy każda tabela
- patientsPersonel posługuje się numerem historii choroby, mrn. Zastępcze id zostaje wewnętrzne.
- doctors / departmentsProsta relacja jeden do wielu. Specjalizacja należy do lekarza, nie do oddziału.
- appointmentsWizyta ambulatoryjna. Zapisuje pacjenta, lekarza, termin i wynik.
- admissionsPobyt na oddziale. Dopóki trwa, discharged_at ma wartość NULL.
- medications / prescriptionsRecepta jest przypięta do wizyty, bo to wizyta daje kliniczny kontekst zlecenia.
Decyzje projektowe warte przejęcia
- Wizyty i hospitalizacje to osobne tabele, a nie jedna tabela wizyt z kolumną typu. Prawie nie mają wspólnych kolumn. Po połączeniu pojawiłyby się NULL-e, których znaczenie zależy od typu.
- Recepta odwołuje się do wizyty, a nie osobno do pacjenta i lekarza. Wizyta jest potrzebna do audytu, a pacjenta i lekarza da się znaleźć przez nią.
- NULL w discharged_at znaczy „wciąż na oddziale”. To fakt, o który można zapytać. Osobny tekst statusu trzeba by ciągle aktualizować.
SQL
Dialekt PostgreSQL. Ten SQL jest już wklejony w narzędzie powyżej. Możesz go swobodnie skopiować do swojej bazy albo do migracji.
CREATE TABLE departments (
id bigserial PRIMARY KEY,
name varchar(80) NOT NULL UNIQUE
);
CREATE TABLE doctors (
id bigserial PRIMARY KEY,
department_id bigint NOT NULL REFERENCES departments(id),
full_name varchar(120) NOT NULL,
specialty varchar(80) NOT NULL
);
CREATE TABLE patients (
id bigserial PRIMARY KEY,
mrn varchar(20) NOT NULL UNIQUE,
full_name varchar(120) NOT NULL,
born_on date NOT NULL,
blood_type varchar(3)
);
COMMENT ON COLUMN patients.mrn IS 'Numer historii choroby – identyfikator, którego używa personel';
CREATE TABLE appointments (
id bigserial PRIMARY KEY,
patient_id bigint NOT NULL REFERENCES patients(id),
doctor_id bigint NOT NULL REFERENCES doctors(id),
at timestamptz NOT NULL,
status varchar(20) NOT NULL DEFAULT 'booked',
notes text
);
COMMENT ON COLUMN appointments.status IS 'umówiona -> odbyta, albo nieobecność / odwołana';
CREATE TABLE admissions (
id bigserial PRIMARY KEY,
patient_id bigint NOT NULL REFERENCES patients(id),
ward varchar(40) NOT NULL,
admitted_at timestamptz NOT NULL,
discharged_at timestamptz
);
COMMENT ON COLUMN admissions.discharged_at IS 'NULL, dopóki pacjent leży na oddziale';
CREATE TABLE medications (
id bigserial PRIMARY KEY,
name varchar(120) NOT NULL,
form varchar(40) NOT NULL
);
COMMENT ON COLUMN medications.form IS 'tabletka / zastrzyk / syrop …';
CREATE TABLE prescriptions (
id bigserial PRIMARY KEY,
appointment_id bigint NOT NULL REFERENCES appointments(id),
medication_id bigint NOT NULL REFERENCES medications(id),
dosage varchar(60) NOT NULL,
days int NOT NULL
);Najczęstsze pytania
Gdzie umieścić badania laboratoryjne?
Potrzebne są dwie tabele. lab_orders odwołuje się do wizyty, tak jak recepty. lab_results odwołuje się do lab_orders: jeden do jednego albo jeden do wielu, jeśli badanie zwraca kilka wartości.
Czy jedna tabela lekarzy wystarczy też dla pielęgniarek i personelu?
W schemacie na zajęcia wystarczy tabela staff z kolumną roli. Prawdziwe systemy rozdzielają personel medyczny, bo grafiki, uprawnienia i wynagrodzenia się różnią. Zacznij prosto i rozdziel, gdy zażąda tego zapytanie.