ErdDocs

Примеры / Система больницы

Система больницы

База данных больницы строится вокруг двух таблиц событий. Приём – это амбулаторный визит к врачу, госпитализация – пребывание в отделении. Обе таблицы ссылаются на пациента. Назначения выписываются на приёме и ссылаются на справочник лекарств.

Ниже 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 с колонкой роли. В реальных системах клинический персонал разделяют, потому что графики, лицензии и оплата у всех разные. Начните с простого и разделите, когда этого потребует запрос.

Другие примеры