Как хранить данные, которые могут быть структурированными или неструктурированными одновременно? - PullRequest
1 голос
/ 29 октября 2009

У меня есть база данных со следующей таблицей:

PATIENT (PATIENT_ID*, MEDICAL_EXAMINATIONS)

, где поле MEDICAL_EXAMINATIONS содержит произвольное описание экзаменов, проведенных пациентом.

Недавно было решено, что о медицинском обследовании можно сообщать ЛИБО как в произвольном тексте (как всегда) ИЛИ структурированным образом (разделенное на название обследования, дату, результаты и т. Д.).

Поэтому я решил изменить схему следующим образом (поля, отмеченные звездочкой, составляют ключ):

PATIENT (PATIENT_ID*, MEDICAL_EXAMINATIONS)
MEDICAL_EXAMINATION (PATIENT_ID*, NUMBER*, NAME, DATE, RESULT)

но я нашел это решение немного тревожным, потому что у меня ОДИНАКОВАЯ информация (медицинские осмотры) хранится в ДВУХ таблицах. В этом случае результат запроса «выбрать все медицинские осмотры, предпринятые пациентом» не будет таким «элегантным».

Я действительно не знаю, как выразить свой вопрос, но эта ситуация мне кажется странной. Мне интересно, если проблема возникает внутренне из спецификаций (что я не могу изменить) или есть лучший способ для моделирования "двух версий" данных.

Ответы [ 9 ]

3 голосов
/ 29 октября 2009

Лично я бы полностью отделил концепцию медицинских осмотров от пациента на две отдельные таблицы, например:

PATIENT(PATIENT_ID)
MEDICAL_EXAMINATION(PATIENT_ID,NAME,DATE,RESULT)
MEDICAL_EXAMINATION_NOTES(PATIENT_ID,NOTES)

«Примечания» - это грубое предположение в отношении имени таблицы, для этого может быть более подходящее имя в зависимости от вариантов использования.

Это дает вам некоторую дополнительную гибкость, поскольку в будущем вы можете пройти несколько экзаменов в произвольной форме, если вы выберете.

Выбор обоих из них всегда будет проблематичным, поскольку у вас другая структура данных. Вероятно, вы будете ограничены наименьшим общим знаменателем и вытянете их в виде строк, если захотите собрать их вместе, например:

SELECT 'Name ' + NAME + ', Date ' + DATE + ', Result: ' + RESULT AS EXAM
FROM MEDICAL_EXAMINATION WHERE PATIENT_ID = @PATIENT_ID

UNION ALL

SELECT NOTES AS EXAM FROM MEDICAL_EXAMINATION_NOTES WHERE PATIENT_ID = @PATIENT_ID

Еще лучше, если эта база данных поддерживает какие-то бизнес-объекты, есть отдельный класс для «произвольной» и «структурированной» экспертизы, а затем общий интерфейс, который дает строковое представление медицинского обследования. Таким образом, у вашего бизнес-уровня есть возможность обрабатывать их по отдельности или использовать их вместе.

2 голосов
/ 29 октября 2009

Одно из основных правил реляционных баз данных было выражено Джо Селко как «Один факт, одно место, один путь» (иногда добавляется «Один раз»). Наличие данных - очень важных данных, по их внешнему виду - дважды представленных в базе данных, хранящихся в двух очень разных модах, не очень хорошая идея. Не могли бы вы сделать что-то вроде этого:

  • Если для экзамена необходимо указать ключевые факты, создайте для них столбцы (как для «Имя», «Дата», «Результат»)
  • Учитывая это, что еще может быть включено в описания? Я бы попытался представить это отдельно и сохранить в отдельной колонке (скажем, Комментарии)
  • С этим вы можете на лету создать «стандартизированное» текстовое описание на основе соответствующих данных.

Что-нибудь еще, и вам придется разобраться в двух разных и потенциально противоречивых источниках вашей информации.

2 голосов
/ 29 октября 2009

Это не очень хорошая ситуация. Один из подходов, который может быть немного чище, - это исключить медицинское обследование из таблицы пациентов (оно там в любом случае не принадлежит), и у таблицы медицинского обследования должны быть Patient_id, имя, дата, результат и free_text. Если введено значение free_text для данной строки, остальные игнорируются. Это означает, что вы не можете, например, сделать дату обязательным полем в БД, но я думаю, что она все же лучше текущей версии.

Это также даст вам путь к переходу от худших к лучшим данным:

Фаза 1: у большинства пациентов есть единственная связанная строка medical_examination со свободным текстом, который описывает несколько экзаменов.

Этап 2: у большинства пациентов есть несколько связанных строк медицинского обследования с произвольным текстом, описывающим каждый отдельный экзамен.

Фаза 3: у большинства пациентов есть несколько связанных строк медицинского обследования с структурированными данными для каждого отдельного обследования.

2 голосов
/ 29 октября 2009

Я бы сделал:

  • Пациент: удостоверение личности, имя, дата рождения, обследования и т. Д.
  • Медицинский осмотр: ID, ID пациента (FK), Имя, Дата, Результат

Думайте о поле свободного текста Patient.Examination как о необработанных или еще не транскрибированных экзаменах. Идея состоит в том, что, когда вы транскрибируете данные из свободного текстового поля, вы удаляете их оттуда и добавляете в другую таблицу.

Тем не менее, это приводит к всевозможным проблемам обнаружения и контроля ошибок. Медицинская транскрипция - деликатная область (понятно).

Возможно, вы могли бы далее нормализовать это и описать каждое возможное обследование, дать ему идентификатор и другие данные, а затем поместить идентификатор обследования в сущность медицинского обследования вместо простого столбца Имя.

Но все зависит от ваших требований.

0 голосов
/ 29 октября 2009

"Недавно было решено, что о медицинском обследовании можно сообщать ЛИБО как в произвольном тексте (как всегда) ИЛИ структурированным образом (разделенное на название обследования, дату, результаты и т. Д.)."

Это кажется мне нерешением (вероятно, сделанным не cognoscenti). Из того, что я могу из этого сделать, это так называемое «решение» все еще оставляет провайдеру информации свободу предоставлять информацию любым способом, каким он хочет, структурированным или неструктурированным. (Примечание: мой ответ не применяется, если поставщик информации вынужден сделать окончательный выбор между «структурированным» и «неструктурированным».)

«Структурированный» означает, что существуют «правила размещения» (например, CSV) и «правила содержимого» (например, «examName должно быть названием известного курса / экзамена»), которым должен соответствовать поставщик информации.

Но «неструктурированный» по определению все еще будет означать, что «любую информацию, которую предоставляет поставщик информации, эта информация всегда будет по меньшей мере удовлетворять« неструктурированной », поэтому любая предоставленная информация, по определению, всегда приемлема в соответствии с «неструктурированная» интерпретация.

Таким образом, это так называемое «решение разрешить структурирование» не имеет для вас никакого смысла . И (принимая во внимание оговорку, которую я упомянул), логический вывод заключается в том, что «вообще ничего не делать» с этим решением (которое кажется абсолютно ложным) - ваш лучший вариант.

Без сомнения, вы подумаете: «Но я просто не могу этого сделать». Вы можете быть правы, если ваше руководство абсолютно нечувствительно к логически обоснованным рассуждениям.

PS

Что касается сделанного замечания "" Один факт, одно место, один путь ": такие случаи могут служить иллюстрацией того, почему иногда необходимо ослабить это (ВРЕМЕННО!) До" Один факт, одно место " «Один из двух возможных способов». Просто для того, чтобы ускорить переход на скорость пользователей.

0 голосов
/ 29 октября 2009

Это сложная проблема, и у вас есть несколько хороших ответов, что я нахожусь в процессе голосования, когда я их интерпретирую.

Мой личный путь состоял бы в том, чтобы разделить столбец исследований свободного текста из строк пациента. В большинстве физических моделей это будет ntext, text или varchar (MAX) или аналогичные, и вы не хотите, чтобы они занимали место в строке, и эти типы обычно хранят свои данные вне строки, но в любом случае это хорошо, чтобы получить это. Как правило, я бы с 1-1 на пациента. Это делает ваши ряды пациентов меньше и более управляемыми.

Тогда я бы сделал отдельную таблицу, где данные интерпретируются, извлекаются и нормализуются в столбцы и строки, многие-1 для пациента.

Вы говорите, что данные одни и те же. Если это так, свободный текст не нужно сохранять, и вы можете использовать нормализованную таблицу экзаменов (и даже составить представление для восстановления исходного «свободного текста»)

На самом деле я обычно воспринимаю свободный текст как устаревший и ограничиваю доступ к нему, а также извлекаю все представления и обновления из нормализованных данных. Если свободный текст необходимо поддерживать синхронно с нормализованной версией, есть ряд методов для обработки этого, таких как триггеры, но они могут быть очень запутанными, если отдельные транзакции могут изменяться, а «свободный текст» должен иметь некоторые запчасти изменены.

0 голосов
/ 29 октября 2009

То, что мы имеем здесь, является примером полуструктурированных данных, один из способов справиться с этим - использовать поле типа XML для ExamDetails. Вы могли бы иметь:

<root>
 <ExamName></ExamName>
 <ExamResult></ExamResult>
 <FreeText></FreeText>
</root>

Не все элементы должны присутствовать в каждой записи. Вы бы использовали свои возможности XML БД для запроса поля. Все мэры БД (MS SQl Server, Oracle, DB2) могут хранить и запрашивать XML.

Еще несколько нот :
У меня было бы минимум три таблицы: пациент, доктор, экзамен

TABLE Patient (ID (PK), Name, other patient details...)
TABLE Doctor (ID (PK), Name, other doctor details...)
TABLE Exam (ID (PK), PatientID (FK), DoctorID (FK), Date, ExamDetails XML, more here...)

Если и врач, и пациент оказываются людьми (в отличие от ветеринарной клиники или осмотра дома), вы можете добавить таблицу «Пациент» и «Пациент» и «Подкатегория» к таблице «Персона» - таким образом легко врач в поликлинике тоже как пациент. Например:

TABLE Person (ID (PK), FirstName, LastName, Phone, Address, other details common to people...)
TABLE Patient (PersonID (PK, FK), ...specific patient details only)
TABLE Doctor (PersonID (PK, FK), ...specific doctor details only)
TABLE Exam (ID (PK), PatientID (FK), DoctorID (FK), Date, ExamDetails XML, more here...)

Поскольку «Пациент» и «Доктор» относятся к типу лиц, PersonID должен совпадать с номером в таблице «Персона».

clinic_model

0 голосов
/ 29 октября 2009

Вы можете добавить комментарий к столбцу в таблицу MEDICAL_EXAMINATION.

Это будет выглядеть

MEDICAL_EXAMINATION (PATIENT_ID, NAME, DATE, RESULT,comment)

Таким образом, вы можете хранить неструктурированные данные в колонке комментариев.

0 голосов
/ 29 октября 2009

Вы можете добавить столбцы ИМЯ, ДАТА, РЕЗУЛЬТАТ в таблицу ПАЦИЕНТ. Если условие «иметь данные в свободной форме или структурированные данные, но не оба» должно выполняться, вы можете добавить триггер, который предотвращает нарушение условия.

...