在我还在学习的时候,请耐心等待。基本上,从抽象的角度来说,我有一组数据可以很容易地适应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的百分比?不是一个好主意。
所以我想知道,我只是将所有任务塞进一个字段,并指定一个分隔符?然后我可以使用split和join或regexp来格式化数据。在这个例子中,我的任务由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
条目进行更改或更改任务顺序都不会很好。
在桶中射鱼并在砧板上使用刀具都可以用来制作寿司......
所以我想知道将Tasks数据放在一个单独的表中,共享相同的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个字节,仍然比我要存储的字符串小。我的代码将在枚举中读取,在运行时存储,并使用它来引用字符串。
不确定这是否是一种有效的技术,如果有更好的方法来解决这个问题,甚至是什么。索引?或者那是不同的东西?或者某些数据库是否可以自动完成?
无论如何,回到主要问题,如何处理我的任意依赖顺序的任务列表?为每个主记录创建一次性表,每个表都有自己的ORDER(键)和Task(string / int / enum)条目?开销似乎更糟糕。
在我看来,这是一个基本问题,并有一些标准的方法来接近它。在我有限的预算,缺乏书籍,缓慢的连接,以及谷歌无休止地送我无处,我想我会要求任何提示。任何免费在线参考知识来源(特定网站或文章)也欢迎。
答案 0 :(得分: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子句(为此,我们需要一个定义顺序的显式列,例如上面的POSITION)。
GOAL_TASK的主键{GOAL_ID,POSITION}确保没有两个任务可以占用给定目标的相同位置。
GOAL_TASK中的UNIQUE约束U1确保同一任务不能多次连接到同一目标。如果要允许这样的重复,可以轻松删除该约束。
如果您对数据库建模感兴趣,可以查看ERwin Methods Guide。
1 这是DBMS的实现细节,但请参阅clustering。
答案 1 :(得分:0)
你的短语“必须维持秩序”至少意味着两件事。
这可能意味着必须在商店时保留订单,方法是将新商品放在一个能够使其保持有序的位置。
这也可能意味着必须通过以正确的顺序检索项目来维持订单的检索时间。
如果你的意思是上面的第二件事,那就相当容易了。您还需要一个列,一个可以显式正确排序的列。例如,儿童可能按姓氏(字母)或年龄或数量(数量)进行排序。书籍可以按其标题或图书馆检索编号进行排序。
然后,当您想要检索项目时,只需在执行检索的SQL查询中包含“order by”子句。无论它们存储的顺序如何,它们都将按您指定的顺序交付。
通过创建适当的索引,可以更快地完成此检索过程。成本是添加新项目会运行得慢一点,索引会占用一些磁盘空间。
在某些情况下,指定正确的顺序需要多个列。
但这涵盖了最简单的情况。