我的数据库技能充其量只是平庸,我必须为调查数据设计一个数据模型。我对此进行了一些思考,现在我觉得我被困在某种 EAV model 之间。以及涉及数百个表的设计,每个表有数百列(和数千条记录)。一定有更好的方法来做到这一点,我希望这个论坛上的聪明人可以帮助我。
我的问题是:我应该如何在 RDBMS 中对调查问题的答案进行建模?必须使用 SQL Server。因此,本次讨论应排除替代数据存储系统。 (当然,有些应该并且将会被评估,但请不要在这里。)我不需要整个数据模型的解决方案,现在我只对答案部分感兴趣。
我已经搜索了各种论坛,但我找不到真正的解决方案。如果它已经在其他地方给出,请原谅我并提供一个链接,以便我阅读。
关于我必须处理的数据的一些假设:
我已经与来自不同背景的人讨论过这个话题,但还没有找到一个好的解决方案。我主要有两种意见。
我能想到的另一种选择是为每种答案类型创建一个表格,即一个用于多项选择题,一个用于自由文本问题等。这不是那么通用,它会导致很多联合连接,我想想,如果发明了新的答案类型,我将不得不添加一个表格。
很抱歉让您厌倦了所有这些文字,并感谢您的投入!
干杯,
亚历克斯
PS:我在这里问了同样的问题:http://www.eggheadcafe.com/community/aspnet/13/10242616/survey-data-model--how-to-avoid-eav-and-excessive-denormalization.aspx
最佳答案
好吧,imgur 已关闭,所以我稍后会发布图片。
我认为这在关系模型中是完全可行的。我已经建立了一个 CDM 来展示我将如何做到这一点。
出站
定义国家调查需要 4 个实体。一些家长调查、国家和问题 list 。您的问题具有内部关系,因此当一个国家/地区“编辑”一个问题时,您可以跟踪该国家/地区提出的问题及其来自的问题。您需要的另一件事是可能的答案实体/表。每个问题都可能有一个相关的可能答案列表(多项选择或范围等)。这 4 个应该完全定义此的“OUTBOUND”方面。
入站
“入站”方只是 2 个新实体,响应者和答案。受访者很直接,如果您认识他们,只需提供该人的人口统计数据,在这里您可以包括回到国家的关系。每个受访者都在特定国家/地区回答了调查。 (如果该人旅行或具有双重国籍,则该人可能与受访者是 1:n 的关系)
答案是基本的;它要么是可能答案列表中列出的选项之一,要么是提供的。暂时不要因为答案可能是数字、日期等而陷入困境。要么是 FK 要么是一串字符。
举报
报告是所有这些的结合...您将选择一个国家和一项调查,获得问题和答案列表。
答案复杂性
取决于您要在哪里进行计算。如果您将 Varchar2(4000) 列用于用户提供的答案,则可以向 question 添加属性以描述答案的数据类型。问:年龄? DT:介于(0 和 130)之间的整数。然后您的集成层可以执行验证而不是数据库执行它。或者您可以有 4 列,其中一列用于数字、日期、字符和 CLOB。您的集成层将确定要使用的列。当您报告这些答案时,您只需使用 Coalesce() 选择所有四列。
这是一个EAV,因为“答案”的数据类型有点模糊
不,这不对。
EAV 模型将实体分解为属性列表。
像这样:
Entity Attribute Value
1 Fname Stephanie
1 Lname Page
1 Age 30
因为您看到调查模式的答案列同时包含单词和数字,就像您认为定义 EAV 的值列在这里一样。它不是。就像我向这个模型添加了 3 个数据类型列一样,它不会从 EAV 改变它。
当时我非常讨厌它
有人告诉我,我正在调整的查询必须“尽可能快”。好吧,给我 10 亿美元和 30 年。 “等等,十亿什么?” “一样多”、“一样快”不是要求。您可以在数据库中验证任何您想要的内容……构建一个 Before 触发器的 shedload,瞧!验证丰富。
年龄列的数据类型是什么?或出生日期列?取决于您的数据源是什么。一些较旧的记录可能只有月份和年份,或者只有年份,或者“大约”或“大约”某年。您不能只有一个数字列并“尽可能多地进行验证”。和 NUMBER(2) 可能是比 NUMBER 更好的验证。所以现在你将拥有 NUMBER(1), NUMBER(2), NUMBER... 来“尽可能多”。
我认为你被绊倒的地方
将此视为概念数据模型,而不是物理模型。在这些术语中,Survey 是一个实体。 Question是一个实体还是只是Survey的一个属性。如果您构建了 One table PER,您会清楚地说明问题只是调查的一个属性,并将它们垂直存储使其成为 EAV。这个模型显示的是 Question 实际上是另一个实体。问题之间存在关系,例如'一个国家[可以]编辑问题'。有原始问题并编辑了一个。每个问题都有一组可能的答案。而最重要的是,都是问题 .在 EAV 中,我称 fname、lname、bdate、age、major、salary 等...所有非常不同的东西,只是属性。在这种情况下,我们不包括发起调查的机构的名称和发布日期以及到期日期等等......作为问题。
让我换一种说法。你是联邦 express 。您想为某些事件存储时间戳。每次包裹进入或离开设施或车辆时。取货车上的时间、下车进入第一个设施的时间、离开该设施并上飞机的时间等。您是否将它们水平存放?怎么提前知道跳数?如果您垂直存储它们,是否会自动使其成为 EAV?如果是这样,为什么。
您是一家气象公司,从全国各地的站点获取临时数据。假设传感器设计为在温度变化 +/- 整度时发送读数。如果你存储一个 sensor_ID|timestamp|temp 是一个阅读表,那是一个 EAV?每个读数都不是传感器的属性,它们本身就是属于集合/系列的实体。
答案的垂直存储与 EAV 的一个共同点是其执行分析查询的难度。如果您想列出所有对问题 5 和 10 回答为 TRUE 而对 6 和 11 回答为 FALSE 的人,如果垂直进行,将非常困难。也许这就是你看到 EAV 的原因。如果你想这样做,你需要一个不同的存储。问题和答案的关系存储不是最好的报告数据库。让我们回到联邦 express 的例子。当行垂直时进行“运输”时间报告并不简单。
关于sql - 调查数据模型 - 如何避免 EAV 和过度非规范化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4626976/