使用1个连接表和3个外键或2个连接表和共享排序?

时间:2015-11-27 08:08:23

标签: sql postgresql database-design junction-table

我有3个表,我正在尝试正确创建之间的关系:

  • 游戏阶段
  • 游戏事件(“游戏阶段”中的一步)
  • 动作窗口('游戏阶段'中完全不同的步骤)

“游戏阶段”可以具有一个或多个“游戏事件”,并且“游戏事件”可以在一个或多个“游戏阶段”中发生。 (许多对多)

“游戏阶段”可以具有一个或多个“动作窗口”,并且“动作窗口”可以在一个或多个“游戏阶段”中发生。 (许多对多)

'游戏事件'与'动作窗口'无关。

然而,我犹豫是否创建了2个单独的联结表,因为“游戏事件”和“动作窗口”共享相同的发生顺序(又名序列)编号系统每个'游戏阶段'。我不确定如何保持这一点。

在能够轻松跟踪出现顺序的同时布置这些表格的最恰当方法是什么?

2 个答案:

答案 0 :(得分:2)

我建议设计代表'游戏事件''动作窗口' 序列 ,相关通过属于相同序列步骤中的相同序列彼此相互依赖。

也就是说,引入“游戏序列”和“游戏序列详细信息”实体,“设计”避免了联结表,表示共享排序事实'游戏事件'和'动作窗口'的意思是在“序列步骤 >游戏序列“(由于考虑到” A'游戏事件'与'行动窗口'无关而避免“)。

SCHEMA

+--------------+ 1      1,n +-------------------+ 1,n
|  game_phase  +------------+  game_phase_play  +----+
|              |            |                   |    |
+--------------+            +-------------------+    |
                                                     |
                                                     | 1
+--------------------------+ 1,n         1 +---------+---------+
|  gaming_sequence_detail  +---------------+  gaming_sequence  |
|                          |               |                   |
++--------+----------------+               +-----+-------------+
 | 1,n    |                                      |
 |        +---+  seq_step                        +---+ seq_steps_number
 |
 |
 |                                      +--------------+
 |                                +-----+  game_event  |
 | 1,n +----------------+         |     |              |
 +-----+  gaming_value  | <-------+     +--------------+
       |                |         |     +-----------------+
       +----------------+         +-----+  action_window  |
                                        |                 |
                                        +-----------------+

前缀

gph_                    === game_phase_
gseq_                   === gaming_sequence_
gv_                     === gaming_value_

TABLES

game_phase              ( id , description, ... )
game_phase_play         ( id , gph_id, gseq_id, date, description, ... )
gaming_sequence         ( id, seq_steps_number, ... )
gaming_value            ( id , type, ... )
gaming_sequence_detail  ( gseq_id, gv_id, seq_step, ... )

我还介绍了一个用于'游戏事件'和'动作窗口'的概括实体,名为“游戏价值“,有用于包含在”游戏序列“中。这种概括可以代表一种游戏不可变的价值(在我们的情况下是2种不同的类型,但是可扩展),因此所选择的命名(已经从“游戏客观化”和“游戏可观察性”切换“)。

这两种类型的

'游戏价值'在游戏序列中通过相等的方式“一起(gseq_id, seq_step)中的gaming_sequence_detail对(可以说这种“配对”是一种关系;这种解决方案更像是代表 sibilings 在序列步骤中,还允许扩展到超过2种类型的'游戏值')。

游戏序列详细信息中的

'游戏事件'和'操作窗口'可以独立修改,也可以可能会出现“ unpaired ”。

gaming_sequence_detail中的约束是,每个seq_step值可以存在一个game_event和一个action_window,因此单个seq_step的最大基数gseq_id是2.

如果是这种情况,相同的gaming_value也可能在同一序列中出现多次。此外,这种设计还可以表示不同的'游戏阶段游戏'之间的共享序列。

答案 1 :(得分:1)

制作一个表格连接点,如:

game_phase_steps

+----+-----------+-------+----------+---------+
| id | phase_id  | rank  |   type   | step_id |
+----+-----------+-------+----------+---------+
|  1 |         1 |    1  | event    |       2 |
|  2 |         1 |    2  | action   |       1 |
+----+-----------+-------+----------+---------+
  • id - game_phase_steps的主键
  • phase_id - 游戏阶段的外键
  • 排名 - 游戏阶段中步骤发生的唯一顺序
  • 类型 - 游戏阶段可以有事件或动作
  • step_id - 用于外部参考游戏事件的event_id或用于外部参考操作窗口的action_id

不知道您的game_eventaction_window是如何构建的。 但是如果您需要单个查询中的所有数据,那么您可能需要执行两个左连接,一个到game_event,一个到action_window,并从相应的连接表返回您想要的字段,如下所示:

game_phase_steps g
LEFT JOIN game_event e
    ON game_phase_steps.type = "event" 
        AND game_phase_steps.step_id = e.id
LEFT JOIN action_window a
    ON game_phase_steps.type = "action" 
        AND game_phase_steps.step_id = a.id

如果你的表结构不同,那么你可能需要这样的select语句:

SELECT CASE WHEN g.type = "event" THEN e.some_field ELSE a.some_field END