数据库设计问题

发布于 2024-11-03 08:22:59 字数 1344 浏览 1 评论 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) 来自 Act,其中 StoryId = ?" 不起作用。)。

然后,我使用 Act.NextId 来了解此操作之后进行哪个操作或挑战。 Act.NextId 可以是行动 PK 或挑战 PK 或故事 PK。这取决于 Act.NextActionType 值。

你怎么认为?这是一个好的设计吗?

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

更新

换句话说,我需要一个系统来知道下一步该去哪里。我会有以下情况:

故事->表演->挑战->表演->挑战新故事 故事->表演->挑战->新故事

注意:行为可以不止一个。

I have a story with lots of acts. These acts are not consecutive (I don't know which is first act or second, third, and so on).

Every story ends with a challenge.

To represent all in a relational database I have used the following tables:

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

I use Story.FirstActId to know which is the first act for story (I'm trying to say that "Select MIN(Id) from Act where StoryId = ?" doesn't work.).

And then, I use Act.NextId to know which act or challenge goes after this act. Act.NextId can be an Act PK or a Challenge PK or a Story PK. This depends on Act.NextActionType value.

What do you think? Is it a good design?

My problem is I have Challenge table without any relationship with any other table.

UPDATE

In other words, I need a system to know where to go next. I will have the following situations:

story->act->challenge->act -> new story
story->act->challente-> new story

NOTE: act can be more than one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

执妄 2024-11-10 08:22:59

您的表设计不是 3NF,并且有可能出现更新异常(例如,如果故事的第一幕被删除,则整个链被破坏;如果其 NextActId 被更新,则链完全改变)。另一个问题是,您必须在链上递归查找以获取故事的所有 Acts,而不是在一个查询中获取它们。

如果您希望能够在故事之间重用行为,则应该使用间接表:

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

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

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

挑战的处理也取决于情况。

挑战也可以是一种行为吗?如果是这样,您应该将其存储在 Acts 中并拥有一个 ActsType 表:

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

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

如果挑战是一个行为,那么它作为挑战的定义是否因其在故事中的位置(最后)而被排除?如果是这样,则 ActsType 不是必需的,它只是 StoriesActMap/Act 上的 MAX 序数。

如果挑战是挑战并且永远不可能是 Act,则应将其存储在单独的表中。如果挑战可以在故事之间重用,您可以使用 StoriesChallengeMap 表;如果不能重用,则可以只使用带有 storyid 键的挑战表将其映射到故事。 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

现在您可以在一个查询中获取故事的所有行动和挑战。请注意,如果没有外键约束,删除故事将导致行为/挑战变得孤立。

Your table design is not in 3NF and has the potential for update anomalies (for example, if the first act of a story is deleted the entire chain is broken; if its NextActId is updated, the chain changes completely). Another problem is that you must recursively seek on the chain to get all of the Acts for a story rather than getting them in one query.

If you want to be able to reuse acts between stories, you should use an indirection table:

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

If you don't need to reuse acts between stories, then you can just stick with the Acts table:

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

The handling of challenges also depends.

Can a challenge also be an act? If so, you should store it in Acts and have an ActsType table:

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

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

If a challenge is an act, is its definition as a Challenge obviated by its position in the story (last)? If so, the ActsType is not necessary, it would just be the MAX ordinal number on StoriesActMap/Act

If a Challenge is a Challenge and can never be an Act, it should be stored in separate table. You can either have a StoriesChallengeMap table if Challenges can be reused between stories, or just the Challenge table with a storyid key to map it to Stories if they cannot be reused. storyid would be a unique key on these tables since a Story only has one challenge.

Assuming that a Challenge is always a Challenge and Acts/Challenges cannot be shared between stories, the design would be as follows:

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

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

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

Now you can get all of the Acts and the Challenge for a story in one query. Beware that a deletion of a story will orphan Acts/a Challenge if there are no foreign key constraints.

凶凌 2024-11-10 08:22:59

我会改变一些事情:

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

No need of ActionType

你会节省空间。如果 NextAct 不为空,则一个 Act 后面跟着一个 Act,
如果挑战不为空,则行动之后是挑战。

当然,条件(NextAct xor Challenge)必须始终为真。您可以通过在 Act 表中的插入中添加表约束来断言这一点。

如果您有很多类型的下一步操作(因为我们这里只有两个操作,所以很容易),您将需要以不同的方式看待问题:
“挑战只有一个行动”,
“一个法案可以有一个法案”
“ActionN has on act”

这样,您将能够找到下一个操作,如下所示:

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。

I would change some things:

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

No need of ActionType

You will save space. An act is followed by an Act if NextAct is not null,
an Act is followed by a challenge if Challenge is not null.

Of course, the condition (NextAct xor Challenge) must always be true. You can assert this by adding a table constraint on insertions in Act table.

If you have a lot of type of next actions (since we only have two actions here, it is easy), you will need to look at the problem in a different way:
"a challenge has one Act",
"an Act can have one Act"
"ActionN has on act"

Like that, you will be able to find the next action as below:

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

At least one will not be NULL.

哥,最终变帅啦 2024-11-10 08:22:59

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

我可能会选择......

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 使其成为第一个 Act,并且当 Act / Challenge 是最后一个项目时该集合(即 Max(Order))将其表示为挑战。

To me, Acts & Challenges seem to store the same kind of information, hence putting them in different tables seems overkill.

I'd probably go for..

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

You could have a flag indicating if something is an Act or Challenge.

However, if I understand your description, then you could identify items by having a convention, e.g. setting the first item's Order as 0 making it the first Act, and when an Act / Challenge is the last item in the set (ie Max(Order)) denoting it as a Challenge.

最佳男配角 2024-11-10 08:22:59

在我看来,挑战只是行动的一种(子)类型。考虑到 Act 表包含 Challenge 中所需的所有列,您只需删除表 ChallengeActionType 即可。如果您需要知道 Act 的类型(标准与挑战),请使用 ThisActionType 列而不是可能包含 C,ANextActionType

还要从 Story 表中删除 FirstActID 并找到一种方法来识别 Act 表中的第一个/最后一个幕 - 每个幕只能属于这个故事中的一个故事model,第一个和最后一个显然很特殊。

因此,完成后,它看起来会像这样

在此处输入图像描述

ActPosition ( F,L,A) 将用于识别第一个、最后一个或任意一个。

The way I see it, the Challenge is simply a (sub)type of Act. Considering that the Act table contains all columns needed in Challenge, you can simply drop tables Challenge and ActionType. Use ThisActionType column instead of the NextActionType which could contain C,A if you need to know what type of Act it is (standard vs challenge).

Also get rid of the FirstActID from the Story table and find a way to identify first/last act in the Act table -- every act can belong to only one story in this model, and first and last are obviously special.

So, by the time it's done it would look something like this

enter image description here

ActPosition (F,L,A) would be used to identify first, last, any.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文