我有一个包含下表的数据库:
PATIENT (PATIENT_ID*, MEDICAL_EXAMINATIONS)
其中字段MEDICAL_EXAMINATIONS
包含患者进行的检查的自由文本描述。
最近,决定将体检作为自由文本(一如既往)或以结构化方式(分为考试名称,日期,结果等)进行报告。
所以我想改变架构如下(标有星号的字段组成键):
PATIENT (PATIENT_ID*, MEDICAL_EXAMINATIONS)
MEDICAL_EXAMINATION (PATIENT_ID*, NUMBER*, NAME, DATE, RESULT)
但我发现这个解决方案有点令人不安,因为我有两个表中存储的相同信息(体检)。在这种情况下,查询“选择患者进行的所有体格检查”的结果并不那么“优雅”。
我真的不知道如何表达我的问题,但这种情况对我来说似乎很明显。 我想知道问题是否源于规范(我无法改变),或者是否有更好的方法来模拟“两个版本”的数据。
答案 0 :(得分:3)
就我个人而言,我会完全将患者的体检概念分成两个单独的表格,如下:
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
更好的是,如果这个数据库支持某种业务对象,则需要一个单独的“自由形式”和“结构化”检查类,然后是一个提供医学检查字符串表示的通用接口。这样,您的业务层可以选择单独处理它们或一起使用它们。
答案 1 :(得分:2)
我愿意:
将Patient.Examination
自由文本字段视为基本上未经处理或尚未转录的考试。我们的想法是,当您从自由文本字段中转录数据时,将其从那里删除并将其添加到另一个表中。
然而,这带来了各种错误检测和控制问题。医学转录是一个微妙的领域(可以理解)。
可以说你可以进一步规范化并描述每个可能的考试,给它一个ID和其他数据,然后将考试ID放入体检实体而不是简单的名称栏。
但这一切都取决于你的要求。
答案 2 :(得分:2)
这不是一个很好的情况。一种可能更清洁的方法是将医学检查留在患者台外(它不属于那里),并且医疗检查表具有patient_id,姓名,日期,结果和free_text。如果输入给定行的free_text值,则忽略其他行。例如,这意味着您不能将日期作为数据库中的必填字段,但我认为它仍然优于当前版本。
它还为您提供了从更差到更好的数据过渡的途径:
阶段1:大多数患者都有一个相关的医学检查行,其中包含描述多项检查的自由文本。
阶段2:大多数患者有多个相关的医学检查行,其中包含描述每个单独检查的自由文本。
阶段3:大多数患者有多个相关的医学检查行,每个单独的检查都有结构化数据。
答案 3 :(得分:2)
Joe Celko将关系数据库的一个主要规则表达为“一个事实,一个地方,一个方向”(有时会添加“一次性”)。拥有数据 - 非常重要的数据,从它的外观 - 在数据库中出现两次,以两种截然不同的方式存储,不是一个好主意。你能做这样的事吗:
还有其他任何内容,您必须通过两种不同且可能不同意的来源对您的信息进行分类。
答案 4 :(得分:0)
您可以将NAME,DATE,RESULT列添加到PATIENT表中。如果条件“包含自由格式或结构化数据,但不是两者都必须”,则可以添加一个可以防止违反条件的触发器。
答案 5 :(得分:0)
您可以将列注释添加到MEDICAL EXAMINATION表。
看起来像
MEDICAL_EXAMINATION (PATIENT_ID, NAME, DATE, RESULT,comment)
因此,您可以将非结构化数据存储在注释列中。
答案 6 :(得分:0)
我们这里有一个半结构化数据的例子,解决这个问题的一种方法是使用ExamDetails
的XML数据类型字段。你可以:
<root>
<ExamName></ExamName>
<ExamResult></ExamResult>
<FreeText></FreeText>
</root>
并非所有元素都必须存在于每条记录中。您将使用数据库XML功能来查询该字段。所有市长数据库(MS SQl服务器,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...)
如果医生和患者恰好都是人(而不是兽医诊所或房屋检查),您可以在Person表中添加一个表Person和子类型Patient和Doctor表 - 这样就很容易医生在诊所作为病人。例如:
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...)
因为Patient和Doctor是person的类型,PersonID应该与Person表中的ID相同。
答案 7 :(得分:0)
这是一个很难解决的问题,你在这里有几个很好的答案,因为我在解释它们时正处于上升的过程中。
我的个人途径是将自由文本检查列从患者行中分离出来。在大多数物理模型中,它将是ntext,text或varchar(MAX)或类似物,并且您不希望它占用行中的空间,并且这些类型通常将其数据存储在行外,但无论如何,把它拿出去很好。通常情况下,我会对患者进行1-1。它使您的患者行更小,更易于管理。
然后我会创建一个单独的表,其中数据被解释,提取并标准化为列和行,与患者一起多次。
你说数据是相同的。如果是这样,则无需保留自由文本,您可以使用标准化的考试表(甚至可以查看重建原始“自由文本”)
实际上,我通常会将自由文本视为旧版并限制对其的访问,并从标准化数据中驱动所有视图和更新。如果需要将自由文本与规范化版本保持同步,那么有许多技术可以像触发器一样处理这个问题,但如果允许单个事务发生变化并且“自由文本”需要有一些,那么它们可能会非常混乱零件改变了。
答案 8 :(得分:0)
“最近,决定医学检查可以作为自由文本(一如既往)或以结构化方式(分为考试名称,日期,结果等)报告。”
这让我觉得这是一个非决策(可能是非认知的)。从我所能做到的,这个所谓的“决定”仍然让信息提供者能够以他想要的任何方式,结构化或非结构化的方式提供信息。 (注意:如果信息提供者被迫在“结构化”和“非结构化”之间做出明确的选择,我的回复不适用。)
“结构化”意味着信息提供者必须遵守“布局规则”(例如CSV)和“内容规则”(例如“examName必须是已知课程/考试的名称”)。
但根据定义,“非结构化”仍将保留“信息提供者提供的任何信息,信息始终至少满足”非结构化“的含义,因此根据定义,所提供的任何信息在“非结构化”解释。
因此,这个所谓的“允许结构化的决定”对你来说根本不可能使用。并且(考虑到我提到的警告),合乎逻辑的结论是,“没有做任何事情”这个决定(这似乎是完全假的)是你最好的选择。
毫无疑问,你会想到“但我不能那样做”。如果您的管理层对逻辑上有充分理由的推理完全不敏感,那么您可能是对的。
PS
关于“一个事实,一个地方,一个方向”的评论:这些案例可能说明为什么有时需要放松(暂时!)“一个事实,一个地方,两种可能的方式之一“。只是为了促进用户的过渡步伐。