问题标签 [normalization]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
416 浏览

database-design - DB Design:什么时候应该创建一个公共属性的超类?

为了描述我的困境,让我首先从一个示例问题开始(从这里偷来的)。假设您的数据库中有一个 GradStudent 表,如下所示:

但是只有助教才有课程作业,只有研究助理才有研究资助,所以这两者中的一个永远是空的。显然这不是最优的,最好这样做:

其中 TeachAsst 和 ResearchAsst 具有来自 GradStudent 表的外键(可能是“studentID”代理)。

我也理解为什么最好制作两个完全独立的表格,例如:

因为您重复了许多具有相同含义的属性。

但是,如果两个不同的类几乎没有任何共同的领域,那么它们是有意义的(我认为),例如:

在这里,它们只有一个共同的“name”,所以让一个 GradStudent 超类只有一个“name”属性会很愚蠢吗?转折点在哪里?您如何决定何时拥有公共信息的超类,或何时让两个类完全分开?拥有超类会使大部分 CRUD 变得更加困难,因为要创建或更新 TeachAsst,您需要更改两个表,而不仅仅是一个。

再举一个例子,假设您正在处理的数据库涉及测量不同电子设备上的信息。虽然相机和手机具有相同的长度/宽度/高度,但大多数其他测量值不会重合(例如,相机不会有任何音频信息,手机不会有任何镜头或视口测量值)。因此,拥有一个完全独立的 cameraData 表和一个 mobileData 似乎几乎更简单,而不是将它们的少量公共信息放入一个超类表中。你怎么看?是否有一条一般规则说您应该始终将公共数据放在一个超类中,即使它只是子类描述性数据的一小部分?

编辑:假设在研究生示例中,研究生要么是助教,要么是研究助理,永远不会转换角色,也永远不会两者兼而有之。

0 投票
7 回答
910 浏览

sql - SQL VIEW 是否应该始终处于 1NF 中?

SQL VIEW 是一个全局的逻辑表,可能会或可能不会被持久化。但它仍然是一张桌子。因此,视图是否应该始终遵循第一范式(1NF)?即没有重复的行,只有标量类型,没有从上到下或从左到右的顺序等。更高的范式呢?

对我来说,我的应用程序“消耗”存储过程的结果,我的视图被 SQL 查询“消耗”,这两种用法是互斥的(即我不使用 SQL 查询存储过程的结果集,而我的应用程序不包含 SQL 代码)。我见过其他人使用 VIEW 将一列中的多个值“连接”成一行,通常是逗号分隔的格式。在 SQL 查询中针对这样的列编写谓词需要类似于以下内容:

所以在我看来,期望所有可以查询的表只包含标量类型似乎是合理的。我这么想是不是太“纯粹”了?

0 投票
9 回答
7083 浏览

database-design - 如何在列上存储元数据

假设您正在收集有关即将上映的超级英雄电影的内幕信息,并且您的主电影表如下所示:

表格1

一般来说,这应该工作得很好,并且允许非常简单的查询以及行之间的比较。

但是,您想跟踪每个数据事实的来源,以及发现该事实的记者的姓名。这似乎暗示了某种像这样的EAV表:

表 2

虽然它很容易捕获我们想要的元数据,但它使查询变得更加困难。简单地获取一部电影的所有基本数据需要更多的时间。更具体地说,您必须在此处处理四行才能获得有关绿灯侠的四个重要信息,而在表 1 中它是一个单独的、很好封装的行。

所以我的问题是,鉴于我刚刚描述的复杂性,并且因为我知道通常要避免使用 EAV 表,EAV 仍然是最好的解决方案吗?它似乎是表示这些数据的唯一合理方式。我看到的唯一另一种选择是将表 1 与另一个包含如下元数据的表结合使用:

表3

但这是非常危险的,因为如果有人将表 1 中的列名更改为“Villain”为“Primary Villain”,那么表 3 中的行仍然会简单地说“Villain”,因此相关数据将不幸解耦。如果“属性”列链接到另一个用作表 1 列枚举的表,这可能会有所帮助。当然,DBA 将负责维护此枚举表以匹配表 1 的实际列。并且实际上,通过使用 SQL Server 中包含表 1 中列名称的系统视图,而不是手动创建枚举表,实际上可能会进一步改进这一点。虽然我不确定你是否可以拥有涉及系统视图。

你有什么建议?EAV是唯一的出路吗?

如果它只有一个元数据列(只有“来源”,没有“记者”)——是否仍然需要走 EAV 路线?你可以有“Director”、“Director_Source”、“Leading Male”、“Leading Male_Source”等列,但这很快就会变得丑陋。有没有更好的解决方案我没有想到?

如果我没有澄清任何观点,请发表评论,我会根据需要添加更多内容。哦,是的,我使用的电影数据是捏造的:)

编辑:为了简明扼要地重申我的主要问题,我希望表 1 具有简单性和真正的 RDBMS 设计,它确实很好地描述了电影条目,同时仍以安全且可访问的方式存储属性上的元数据。这可能吗?还是 EAV 是唯一的方法?

编辑 2:在做了更多的网络研究之后,我还没有找到关于 EAV 的讨论,该讨论围绕着在列上存储元数据的愿望。实现 EAV 的主要原因几乎总是动态且不可预测的列,而在我的示例中并非如此。在我的例子中,总是有相同的四列:导演、男主角、女主角、反派。但是,我想为每一行存储关于每一列的某些事实(来源和记者)。EAV 会促进这一点,但我想避免诉诸于此。

更新

使用表 2 设计,除了将列“Movie”重命名为“Name”并将整个表称为“Movie”之外,这是 SQL Server 2008 中用于取回表 1 的数据透视操作:

0 投票
3 回答
142 浏览

database-design - “反驳”和“评论”——两个 DB 表还是一个?

我正在为一个朋友做一个项目,我遇到了一个艰难的决定。该项目由论文组成,每篇论文都可以提出质疑,也可以发表评论。事情是这样的,只有一个人能够挑战论文,然后其他人都被锁定,只能发表评论。

反驳只能是两个深度的回应,第一个2000字,第二个500字。那时,没有更多的反驳——如果观众觉得话题没有用尽,剩下的讨论将在评论中进行(n 个字符的固定长度,与反驳不同)。

所以我最初决定反驳和评论在结构上是一样的,我只会在我的评论表中添加一个布尔字段来指示评论是否是_rebuttal。但我对这个方向有点不确定。

集体——你会建议什么?每篇文章只能在两个人之间进行讨论,并且两个人只能发言 2 次。与评论非常相似,但分开。

0 投票
4 回答
490 浏览

sql-server - 请帮助解释我是否为了性能而破坏我的数据库架构:(

在 Sql 2008 上(之前是 05 年),我在生产中使用了将近 3 年的数据库。一直很好,但性能不是很好。所以我正在调整架构和查询以帮助加快一些事情。此外,每张主表包含大约 1-3 个轧机行(以提供对大小的 ua 估计)。

这是一个示例数据库图(Soz,在 NDA 下,所以我无法显示原件):-

替代文字 http://img11.imageshack.us/img11/4608/dbschemaexample.png

注意事项(与我的问题直接相关):-

  • 车辆可以有 0 (NULL) 或 1 个 Radio。(左外连接)
  • 车辆可以有 0 个(NULL)或 1 个杯托(左外连接)
  • 车辆有 1 种轮胎类型(内连接)。

首先,这看起来像一个规范化的数据库模式。我很烂,DB理论,所以我猜这是3NF(至少)......著名的遗言:)

现在,这正在扼杀我的数据库性能,因为这两个外连接和内连接被调用了很多,并且在许多语句中还有一些连接。

为了尝试解决这个问题,我想我可以尝试indexed view。创建视图是小菜一碟。但是索引它不起作用->无法使用连接或自引用表创建索引视图(也是另一个问题:()。

所以,我已经哭了好几个小时(和/wrists染了头发写了一首关于它的 emo 歌曲并将它放在 myfailspace 上)并做了以下事情......

  1. 在每个“可选”外部连接表中添加了一个新行(在本例中为 Radios 和 CupHolders)。ID = 0,其余数据 = 'Unknown Blah' 或 0。
  2. 更新父表,使任何 NULL 数据现在都有一个 0。
  3. 将关系从外部联接更新到内部联接。

现在,这行得通。我什至可以制作索引视图,现在速度非常快。

所以……我很痛苦。这与我所学的一切背道而驰。我觉得脏。独自的。已感染。

这是一件坏事吗?这是为了性能而对数据库进行非规范化的常见场景吗?

我很想对此有一些想法,请:)

PS。谷歌随机找到的那些图片——所以不是我。

0 投票
3 回答
446 浏览

language-agnostic - 有哪些方法可以映射和规范化相关数据?

假设您需要将提供给您的随机相关数据汇集到更简洁的类别中。

示例 - 为您提供以下数据。注意- 可能有任何数量的其他相关的柱状数据:

任务 - 将上述内容合并并规范化为干净的预定义分组:

请不要担心完成的数据将如何持久化。而是专注于如何坚持和管理分组规则。

只有一个假设:您不能使用数据库来保存分组规则。因此,当我们说“规范化”时,我们并不是在说关系数据库规范化规则。但是,我们希望从数据输入中消除不一致(如上所示),以使随机数据进入一致状态。

那么有哪些可用的选项?保持技术不可知论:

XML?

配置文件?

设置文件(编译与否)?

.ini 文件?

代码?

等等

列出每个答案的优缺点。虽然这确实是一个 excersize,但这是一个现实世界的问题。因此,假设您的客户/雇主已委托您完成此任务。

0 投票
3 回答
557 浏览

normalization - 标准化具有多个来源的成就

我正在寻找一个好的算法推荐。

我有用户和成就。用户创建成就,然后将其提供给其他用户。与每个成就相关联的是用户指定的点值。一个用户的总分是他们所有成就的总和。

基本上:

好的,所以这个系统显然非常适合游戏。您可以创建许多帐户并互相取得大量成就。我试图通过将点值缩放到与用户指定的不同的值来减少一点。

  1. 假设所有用户都是诚实的,但他们只是很难以不同的方式衡量。我应该如何标准化点值?AKA 一个用户为每个简单的成就给出 5 分,另一个给出 10 分,我怎样才能将它们标准化为一个值。目标是分数与难度成正比的分布。
  2. 如果一个用户不擅长判断分值,我如何根据获得成就的用户数来判断难度?
  3. 假设用户可以大部分被划分为不相交的组,其中一个用户将成就授予一整套其他用户。这对前两种算法有帮助吗?例如,用户 A 仅向以奇数结尾的用户授予成就,而用户 B 仅向以偶数结尾的用户授予成就。
  4. 如果每个人都是恶意的,我能离让用户无法过度夸大他们的积分值还有多远?

注意:给予用户的质量与他获得的成就没有任何关系。许多给予者只是机器人,它们自己没有收到任何东西,但会自动奖励用户的某些行为。

我目前的计划是这样的。我有一个从我那里获得成就的人分配 10 分。如果我总共给 55 人发放了 10 个成就,我的分配是 550。然后根据获得它的人数分配给每个成就。如果分布是[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]获得每项成就的人,那么点值将是[50, 25, 16.6, 12.5, 10, 8.3, 7.1, 6.25, 5.5, 5]

欢迎和赞赏我的方法和替代建议的任何问题。另外,发布您能想到的我错过的其他案例,我会将它们添加到列表中。谢谢!

0 投票
2 回答
1894 浏览

database-design - 多对多自引用表

有没有一种好方法来实现单表中的行之间的多对多关系?

示例:存储单词同义词的表:

明显的解决方案导致可能不是 1NF 表,其中包含重复数据:

虽然可以通过添加 (word1 < word2) 检查来处理重复,但它使 SELECT 更加复杂(与普通连接相比,联合)并且非常随意。这种特定情况可以从辅助表中受益(例如“含义”,因此单词是 M:N 链接到共同含义而不是相互链接,从而提供更清晰的模式),但我对一些通用解决方案感兴趣。

那么有没有更好的(希望是通用的)方法来实现这种 M:M 关系?

0 投票
3 回答
5763 浏览

mysql - mySQL 数据库的自动规范化 - 怎么做?

我有一个 mySQL 数据库,其中包含一个 80 列和 1000 万行的巨大表。数据可能不一致。

我想以自动化和有效的方式规范化数据库。

我可以使用 java/c++/... 来做,但我想在数据库中做尽可能多的事情。我想数据库之外的任何工作都会大大减慢速度。

关于如何做的建议?什么是好的资源/教程开始?

不是在寻找关于什么是标准化的任何提示(使用谷歌找到了很多这样的东西)!

0 投票
5 回答
215 浏览

database - 如何在数据库中建模打开/关闭状态?

想象一下,我有一个包含 OrderID (PK)、CustomerID、CustomerOrderN 等列的 Orders 表。现在我需要添加“关闭”订单的可能性,并指定关闭订单的原因(例如“报价对客户来说太高”、“不可用”、“客户要求关闭订单”)。

问题 1.在数据库设计中实现这一点的最佳和正确方法是什么?

我认为最好的方法是创建可以为空的已关闭列(如果订单已打开),如果不为空(即如果订单已关闭),则该值指向另一个表 OrderCloseReasons。

问题 2.如果我已经在 Orders 表中有一个已关闭的布尔列怎么办,现在我需要实现指定关闭原因的可能性。我不能重构太多,因为系统已经不是那么小了,所以很难重构数据库方案。在这种情况下,增加指定关闭原因的可能性的最佳方法是什么?

我认为如果我只是将 CloseReasonID 列添加到 Orders 表中,那就不好了。但我不确定。

先感谢您。