2011-04-27 137 views
0

我有很多行为的故事。这些行为不是连续的(我不知道哪一个是第一个行为或第二个,第三个等等)。数据库设计问题

每个故事都以挑战结束。

,以表示我已经使用了下面的表格关系数据库中的所有:

Story 
--------------------------------------- 
Id    | PK 
Name   | String 
FirstActId  | FK to ACT table 

Act 
--------------------------------------- 
Id    | PK 
StoryId   | FK to STORY table 
Name   | String 
Description  | Very long string 
NextActionType | FK to ACTIONTYPE table 
NextId   | Its value depends on NextActionType 

ActionType 
--------------------------------------- 
Id    | PK 
Name   | Values= 'Act', 'Challenge', 'Story'. 

Challenge 
--------------------------------------- 
Id    | PK 
Name   | String 
Description  | Very long string 
NextActionType | FK to ACTIONTYPE table 
NextId   | Its value depends on NextActionType 

我用Story.FirstActId知道这是故事的第一幕(我想说,"Select MIN(Id) from Act where StoryId = ?"不起作用)。

然后,我用Act.NextId知道该行为之后应该采取哪种行为或挑战。 Act.NextId可以是一个行动PK或一个挑战PK或一个故事PK。这取决于Act.NextActionType的值。

您认为如何?这是一个好的设计吗?

我的问题是我有挑战表与任何其他表没有任何关系。

UPDATE

换句话说,我需要一个系统,要知道接下来要去哪里。我将有以下几种情况:

故事 - > ACT->挑战 - >行为 - >新的故事 故事 - > ACT-> challente->新的故事

注意:行为可以比更一。

+0

如果您不知道哪种行为是第一次,第二次等,您如何存储FirstActId? – 2011-04-27 13:25:26

+0

我知道哪个行为是我添加故事和行为时的第一行为。我试图说:“从Story中选择MIN(Id)where StoryId =?”不起作用。 – VansFannel 2011-04-27 13:27:19

回答

0

我看到它的方式,Challenge只是一个(子)类型的Act。考虑到Act表包含Challenge中所需的全部列,您可以简单地删除表ChallengeActionType。如果您需要知道它是什么类型的行为(标准vs挑战),请使用ThisActionType列而不是NextActionType,其中可能包含C,A

还可以获得从故事表格摆脱FirstActID,并找到一种方法来识别Act表第一/最后一幕 - 每一个行为只能属于一个故事,在这个模型中,并且第一个和最后显然是特别的。

所以,在时间它完成它会是这个样子

enter image description here

ActPosition(F,L,A)将首先用于识别,最后,任何。

+0

我忘了说nextActionType也可以是一个故事。我用更好的细节更新了我的问题。抱歉。 – VansFannel 2011-04-27 13:28:53

+0

@VansFannel,在这种情况下,'NextActID'只会指向不同'StoryID'的第一幕。 – 2011-04-27 13:39:59

0

我会改变一些事情:

Act 
--------------------------------------- 
... 
NextAct   | FK to Act table, can be NULL 
Challenge  | FK to Challenge table, can be NULL 

No need of ActionType 

您将节省空间。如果NextAct不为空,则该行为后跟一个行为 如果挑战不为空,则行为跟随挑战。

当然,条件(NextAct异或挑战)必须始终为真。您可以通过在Act表格中添加一个表格约束来插入。

如果你有很多类型的下一步行动的(因为我们只有两个动作在这里,很容易),你需要看问题以不同的方式: “的质疑有一分法”, “法案能有一个法” “ActionN对行动”

这样,你就可以找到,因为下面的下一个动作:

SELECT 
    challenge_id, 
    act_id, 
    ... 
FROM 
    Act 
LEFT OUTER JOIN 
    Act NextAct ON Act.next_act_id = NextAct.act_id 
... 
LEFT OUTER JOIN 
    Challenge ON Act.challenge_id = Challenge_id 

至少有一个会不会是NULL。

+0

我忘了说nextActionType也可以是一个故事。我用更好的细节更新了我的问题。抱歉。 – VansFannel 2011-04-27 13:29:19

+0

它不会改变任何东西,必须创建一个具有关系儿童 - >父母而不是父 - >子女的树/图结构。 – 2011-04-27 13:39:28

0

对我来说,使徒行传&挑战似乎存储了相同类型的信息,因此把它们放在不同的表格中似乎有点矫枉过正。

我可能会去..

Story 
--------------------------------------- 
Id    | PK 
Name   | String 
FirstActId  | FK to ACT table 

Items (Acts or Challenges) 
--------------------------------------- 
Id    | PK 
StoryId   | FK to STORY table 
Name   | String 
Description  | Very long string 
Order   | Int - which position this Act/Challenge should go in 

你可以有一个标志,指示,如果事情是一种行为或挑战。但是,如果我了解你的描述,那么你可以通过约定来识别项目,例如,将第一项Order设置为0使其成为第一项法案,并且当动作/挑战是该组中的最后一项(即Max(Order))时,将其表示为挑战。

1

您的表格设计不在3NF中,并有更新异常的可能性(例如,如果故事的第一个动作被删除,则整个链条被破坏;如果其NextActId更新,链条完全更改)。另一个问题是,你必须递归地在链上寻找所有的行为来获得一个故事,而不是让他们在一个查询中。

如果你希望能够故事之间重复使用的行为,你应该使用一个间接表:

StoriesActsMap 
-------------- 
storyid 
actid 
ordinal_number 

如果你不需要重用故事之间的行为,那么你可以坚持使用行为表:

Act 
    ------------- 
    actid 
    actDescription, etc. 
    ordinal_number 
    storyid 

挑战的处理也取决于。

一个挑战也是一种行为吗?如果是这样,你应该把它存放在行为和有ActsType表:

Act 
    -------------- 
    actid 
    acttypeid 
    ...see rest of Act above 

    ActsType 
    -------------- 
    acttypeid 
    acttype (Act, Challenge) 

如果一个挑战是一种行为,是其定义为挑战由它的故事(最后)位置消除?如果是这样,ActsType不是必需的,它只是StoriesActMap/Act上的MAX序号。如果一个挑战是一个挑战并且永远不可能是一个行为,它应该存储在单独的表格中。如果挑战可以在故事之间重复使用,或者只有挑战表与storyid键,如果它们不能重复使用,则将其映射到故事,您可以拥有StoriesChallengeMap表。因为故事只有一个挑战,所以storyid将成为这些表格上的唯一键。

假设一个挑战始终是一个挑战和行为/挑战无法故事之间共享,设计将是如下:

Story 
---------- 
storyid 
other info 

Act 
---------- 
actid 
storyid 
actorder (ordinal number of acts, (actorder, storyid) is a prime) 
other info 

Challenge 
---------- 
chid 
storyid 
other info 

现在你可以得到所有的行为和挑战的一个故事在一个查询中。注意,如果没有外键约束,删除故事将孤儿徒/挑战。

+0

在阅读您的问题更新之后,我的设计无法处理故事后的故事。故事总是会跟着挑战吗?或者,故事可以在任何时候成为下一个动作? – 2011-04-27 13:59:32

+0

我正在使用nextActionType和nextId来设置一个'导航'我可以有:story-> act-> challenge-> act-> new story。或者这一个:故事 - >行动 - >挑战 - >新故事。行为可能不止一个。我不确定是否理解你的问题。如果你需要更多的细节,告诉我。 – VansFannel 2011-04-27 15:47:43