Примеры / Система больницы
Система больницы
База данных больницы строится вокруг двух таблиц событий. Приём – это амбулаторный визит к врачу, госпитализация – пребывание в отделении. Обе таблицы ссылаются на пациента. Назначения выписываются на приёме и ссылаются на справочник лекарств.
Ниже ErdDocs рисует эту схему по её SQL, со всеми таблицами и связями. На вкладке «Словарь данных» – справочник для печати, целиком и бесплатно на этой странице. SQL ещё ниже.
Наведите на таблицу, чтобы подсветить её связи, кликните, чтобы закрепить.
Зачем нужна каждая таблица
- patientsПерсонал пользуется номером медкарты, mrn. Суррогатный id остаётся внутренним.
- doctors / departmentsПростая связь «один ко многим». Специальность хранится у врача, а не у отделения.
- appointmentsАмбулаторный визит. В нём пациент, врач, время и итог.
- admissionsПребывание в стационаре. Пока пациент в отделении, discharged_at равен NULL.
- medications / prescriptionsНазначение привязано к приёму, потому что визит задаёт клинический контекст.
Проектные решения, которые стоит взять
- Приёмы и госпитализации хранятся в разных таблицах, а не в одной таблице визитов с колонкой типа. Общих колонок у них почти нет. При слиянии появились бы NULL, смысл которых зависит от типа.
- Назначение ссылается на приём, а не на пациента и врача по отдельности. Визит нужен для аудита, а пациента и врача можно найти через него.
- NULL в discharged_at значит «ещё в стационаре». Это факт, который можно запросить. Отдельную колонку статуса пришлось бы обновлять вручную.
SQL
Диалект PostgreSQL. Этот SQL уже вставлен в инструмент выше, его можно перенести в свою базу или в миграцию и свободно копировать.
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 'Номер медкарты – идентификатор, которым пользуется персонал';
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 'записан -> принят, или не пришёл / отменён';
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, пока пациент в стационаре';
CREATE TABLE medications (
id bigserial PRIMARY KEY,
name varchar(120) NOT NULL,
form varchar(40) NOT NULL
);
COMMENT ON COLUMN medications.form IS 'таблетки / инъекции / сироп …';
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
);Частые вопросы
Куда положить анализы?
Нужны две таблицы. lab_orders ссылается на приём, как и назначения. lab_results ссылается на lab_orders: один к одному или один ко многим, если в одном анализе несколько показателей.
Хватит одной таблицы врачей на медсестёр и персонал?
Для учебной схемы хватит таблицы staff с колонкой роли. В реальных системах клинический персонал разделяют, потому что графики, лицензии и оплата у всех разные. Начните с простого и разделите, когда этого потребует запрос.