2

忍受我,因为我还在学习。从本质上讲,抽象地说,我有一组数据可以很容易地适合 1NF 或 2NF,但也有一些在项目数量上有所不同的数据,我希望这些数据与记录相关联,其中必须保持顺序。请注意,我不关心任何特定的数据库或语言,只关心这个问题的基本方法和理论。

为了简化为最基本的元素,我有一个 ID、一个目标和完成目标所需的任务。对于这个示例,我排除了其他字段,如 Name(字符串)、Section(字符串)等,因为它们易于处理。

起初,我想,也许永远只有 5 个任务,因为数据集的随便一瞥似乎表明大约有 2-3 个任务(字符串)。我的代码中的顺序暗示​​为 1 -> 2 -> 3 等等。

ID (key), Goal (string), Task1, Task2, Task3, Task4, Task5

我立即不喜欢那样,因为一半的值最终为 NULL,但它有点工作,我正在学习其他一些东西,比如如何从我的脚本语言调用 SQL。然后我开始看到有 6、7 和 8 个任务的目标。:( 我是否只是根据需要随机添加更多列,从而增加存储的 NULL 的百分比?不。不是一个好主意。

所以我想知道,我是否只是将所有任务都塞到一个字段中,并指定一个分隔符?然后我可以使用拆分和连接或正则表达式来格式化数据。在此示例中,我的任务由 1-3 个标记组成[A-Za-z '],因此很容易处理。

ID (key), Goal (string), Tasks (string)

Tasks形式在哪里task1,task2,task3,...

这件事似乎让我很困扰。如果我同时处理多个目标,并且想要获得需要应用相同任务集的所有名称的列表,该怎么办?例如,假设我有:

123, "Name1", "Goal1", "task1,task2,task3,task4,task5"
456, "Name2", "Goal2", "task2,task3,task4"
789, "Name3", "Goal3", "task3,task4,task5"

现在查找所有需要的记录变得多么混乱task3?也许我可以使用 LIKE 来找到我想要的东西?似乎是对该功能的可怕滥用。可以将其全部分解,处理脚本中的逻辑,看起来更加混乱,效率低下,难以维护。例如,对所有task3条目进行更改,或更改任务的顺序,都是不好的。

在桶里打鱼和在砧板上用刀子都可以用来做寿司……

所以我想知道将任务数据放在一个单独的表中,共享相同的 ID 键。就是这个样子。

Main Table

123, "Name1", "Goal1"
456, "Name2", "Goal2"
789, "Name3", "Goal3"

Tasks Table

123, "Task1"
123, "Task2"
123, "Task3"
123, "Task4"
123, "Task5"
456, "Task2"
456, "Task3"
456, "Task4"
789, "Task3"
789, "Task4"
789, "Task5"

在这一点上,我的直觉是我的想法出现了可怕的错误。我失去了确保订单得以维持的能力。对任何特定 ID 所需的所有任务的查询可能会导致任何顺序。它还存储了大量冗余数据。至少我摆脱了NULL?但这不好。

在这一点上,还有其他事情困扰着我,这可能应该在设计的早期解决。但我正在努力自学,边走边学。所以我走了,切线。

有很多冗余的文本数据,因为这些任务描述是不变的。所以我想知道如何最好地优化它,以最大限度地减少磁盘使用量并提高速度,而不会因过多的脚本开销而使代码混乱。我的一个想法是创建一个枚举表。

Enumerations: ID (key), Task (string)

1, Task5
2, Task4
3, Task3
4, Task2
5, Task1
6, Task10
7, Task9
8, Task8
9, Task7
10, Task6
and so on.

好吧,至少我可以存储一个小得多的整数,而不是到处存储一个字符串。即使它们是最坏的 64 位整数,也就是 8 个字节,仍然比我要存储的字符串小。我的代码将读取枚举,存储在运行时,并使用它来引用字符串。

不确定这是否是一种有效的技术,是否有更好的方法来解决这个问题,甚至它被称为什么。索引?或者那是什么不同的东西?还是某些数据库可以自动执行的操作?

无论如何,回到主要问题,如何处理我的任意顺序相关任务列表?为每条主记录创建 1-off 表,每个表都有自己的 ORDER(键)和 Task(字符串/整数/枚举)条目?开销似乎更糟。

在我看来,这是一个基本问题,并且有一些处理它的标准方法。在我有限的预算、缺乏书籍、连接缓慢以及谷歌无休止地让我无处可去的情况下,我想我会要求任何提示。也欢迎任何免费在线参考知识来源(特定网站或文章)。

4

2 回答 2

1

你的想法是正确的,你自己非常接近真正的解决方案,我会稍微推动你一点,让你到达那里......

在此处输入图像描述

示例数据:

GOAL
----
123, "Goal1"
456, "Goal2"
789, "Goal3"

TASK
----
1, 'Task1'
2, 'Task2'
3, 'Task3'
4, 'Task4'
5, 'Task5'

GOAL_TASK
---------
123, 1, 1
123, 2, 2
123, 3, 3
123, 4, 4
123, 5, 5
456, 1, 2
456, 2, 3
456, 3, 4
789, 1, 3
789, 2, 4
789, 3, 5

关系数据库中,表是关系的物理表现形式,是一个集合,而集合本质上是无序的。因此,虽然表有一些物理顺序1,但它在逻辑上是无序的,并且保证查询结果顺序的唯一方法是使用 ORDER BY 子句(为此,我们需要一个明确的列来定义顺序,如上面的位置)。

GOAL_TASK 的主键 {GOAL_ID, POSITION} 确保没有两个任务可以占据给定目标的相同位置。

GOAL_TASK 中的 UNIQUE 约束 U1 确保同一个任务不能多次连接到同一个目标。如果您想允许这样的重复,您可以轻松地删除该约束。

如果您对一般的数据库建模感兴趣,可以查看ERwin Methods Guide


1这是 DBMS 的实现细节,但请参阅集群

于 2013-10-20T23:30:55.080 回答
0

您的短语“必须维护订单”可能意味着至少两种不同的东西。

这可能意味着必须在商店时维持订单,方法是将新商品放置在可以保持有序的位置。

这也可能意味着必须在检索时通过以正确的顺序检索项目来维护订单。

如果你的意思是上面的第二件事,那是相当容易的。您还需要一列,该列将使正确的排序明确。例如,孩子可能按他们的姓氏(按字母顺序)或按年龄或按体重(按数字顺序)排序。书籍可能按书名或图书馆检索号排序。

然后,当您要检索项目时,只需在执行检索的 SQL 查询中包含“order by”子句。无论它们以何种顺序存储,它们都将按照您指定的顺序交付。

通过创建适当的索引,可以使此检索过程更快。代价是添加新项目会运行得慢一点,而且索引会占用一些磁盘空间。

在某些情况下,指定正确的顺序需要多于一列。

但这涵盖了最简单的情况。

于 2013-10-20T16:01:29.867 回答