sql - 调查数据模型 - 如何避免 EAV 和过度非规范化?

标签 sql database-design survey

我的数据库技能充其量只是平庸,我必须为调查数据设计一个数据模型。我对此进行了一些思考,现在我觉得我被困在某种 EAV model 之间。以及涉及数百个表的设计,每个表有数百列(和数千条记录)。一定有更好的方法来做到这一点,我希望这个论坛上的聪明人可以帮助我。

我的问题是:我应该如何在 RDBMS 中对调查问题的答案进行建模?必须使用 SQL Server。因此,本次讨论应排除替代数据存储系统。 (当然,有些应该并且将会被评估,但请不要在这里。)我不需要整个数据模型的解决方案,现在我只对答案部分感兴趣。

我已经搜索了各种论坛,但我找不到真正的解决方案。如果它已经在其他地方给出,请原谅我并提供一个链接,以便我阅读。

关于我必须处理的数据的一些假设:

  • 每项调查由 1 至 n 份问卷组成
  • 每份问卷由 100-2,000 个问题组成(请忽略 2,000 个问题听起来确实很多……)
  • 问题可以有多种类型:多项选择、自由文本、数字(如年龄、收入、百分比等)
  • 每个调查涉及10-200个国家(这些不是受访者。受访者实际上是这些国家的人。)
  • 根据调查问卷的类型,每个调查问卷由每个国家 100-20,000 名受访者回答。
  • 一个国家可以调整调查问卷,即添加、删除或编辑问题
  • 一个国家的数据收集在该国家的一个单独的数据库中。从一开始就不可能进行在线集成。
  • 稍后必须整合所有国家/地区的数据。这意味着,例如,如果一个国家删除了一个问题,那么该数据必须以某种方式从他们发送的内容中获得,以便在所有国家/地区实现统一设计
  • 我将不得不编写集成和清理软件,该软件需要处理每个国家的数据
  • 最后需要将数据导出为平面文件,每个国家一个矩形网格和问卷。

  • 我已经与来自不同背景的人讨论过这个话题,但还没有找到一个好的解决方案。我主要有两种意见。
  • 习惯于使用平面文件(电子表格样式)进行数据处理和分析的领域专家投票支持具有大量表格和列的非规范化结构,如上所述(每个国家/地区和调查问卷 1 个表格)。这对我来说听起来很糟糕,因为我了解到要避免使用宽表,在使用它时确定表中实际有哪些列会很烦人,数据库将被数百个表弄得杂乱无章(或者我什至需要设置多个数据库,每个数据库的设计相似但略有不同)等
  • O-O-程序员投票支持强烈“规范化”的设计,这将有效地导致一个中央表,其中包含所有受访者对所有问题的所有答案。该表需要包含类型为 sql_variant 的列或具有不同类型的多个答案列,以存储不同类型的答案(多项选择、自由文本等)。前者本质上是一个 EAV 模型。我倾向于在这里关注 Joe Celko,他强烈反对使用它(他称之为 OTLT 或“一个真正的查找表”)。后者意味着每行将包含设计为不适用类型的空单元格。

  • 我能想到的另一种选择是为每种答案类型创建一个表格,即一个用于多项选择题,一个用于自由文本问题等。这不是那么通用,它会导致很多联合连接,我想想,如果发明了新的答案类型,我将不得不添加一个表格。

    很抱歉让您厌倦了所有这些文字,并感谢您的投入!

    干杯,
    亚历克斯

    PS:我在这里问了同样的问题:http://www.eggheadcafe.com/community/aspnet/13/10242616/survey-data-model--how-to-avoid-eav-and-excessive-denormalization.aspx

    最佳答案

    alt text好吧,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/

    相关文章:

    sql - BigQuery 在同一查询中展平 GA session 和命中级别字段

    sql - 这个数据库设计正确吗?

    sql-server-2005 - 从 SAS 到 SQL 服务器的多种缺失类型

    r - 如何在 Logit 回归的调查数据上使用 GAM (mgcv) 中的样本权重?

    mysql - 将 AUTO_INCREMENT 列存储在其他表中

    sql - mysql中从一个字段提取数据到另一个字段

    php - mysql连接表

    sql - 如何构建 SQL 数据模型以保持数据完整性

    survey - 您的 USB 驱动器上带有哪些开发工具?

    survey - 开发人员在任务之间切换最有效的方式是什么?