如何避免一对多关系中的重复数据

时间:2019-05-16 05:09:21

标签: sql database-design relational-database entity-relationship

考虑以下情况:

有一个Action表,其中包含字段-idstart_timeend_timegroup_id

有一个ActionGroup表,该表具有一组多个操作的字段-idstart_timeend_time(请注意,操作顺序发生)。 / p>

ActionGroupAction具有一对多关系。


例如:

如果有四个Action记录,

enter image description here

相关的ActionGroup记录如下

enter image description here


Action表似乎已经包含ActionGroup表所需的数据,而ActionGroup实际上是在重复它。

是否可以通过简单而高效的方式查询ActionGroup的开始时间和结束时间,而不必分别记录start_time内的end_timeActionGroup字段?

此外,在设计表模式时,像上面那样复制数据是否被认为是不好的做法?

3 个答案:

答案 0 :(得分:1)

首先要回答的最后一个问题:数据重复不好,因为它会带来不一致的风险,例如如果您的ActionGroup 1已向end_time注册(例如)8,而Actionend_time 13已注册。如果数据不一致,则您将无法信任任何数据查询结果,因为不一致的逻辑系统根本无法产生任何结果。

在您的示例中,可以使用聚合查询(关系代数伪代码)从ActionGroup派生Action

Action group by { group_id } add {
  Min(start_time) start_time,
  Max(end_time) end_time
}
rename { group_id id }

–因此,您不需要Action relvar(表)中的那些属性。这很简单;是否足够快取决于您的要求。

但是请注意,如果您确实在start_time中保留了冗余end_timeActionGroup属性,则需要控制冗余(最好使用约束,或者使用触发操作,或者使用最坏的情况是应用程序代码),以避免不一致。这也会影响性能,但它们将适用于写入而不是读取。

答案 1 :(得分:1)

  

我认为您不需要示例中的ActionGroup

在您的示例Action表中,已经具有操作组的所有信息(group_id,start_time,end_time)

您可以只使用Action表来获取start_time和end_time的最小值,最大值,但是如果您需要ActionGroup上的更多字段并获取该组的Actions的start_time和end_time,请尝试类似这个。

SELECT *
FROM `ActionGroup` as action_group
INNER JOIN (
  SELECT group_id, min(start_time), max(end_time)
  FROM ACTION
  GROUP BY group_id) as action
ON action_group.id = action.group_id

答案 2 :(得分:0)

  

看来Action表已经包含了   ActionGroup表需要,而ActionGroup实际上在重复它。

我认为您是对的,您只是根据您的示例在重复一遍。如果仅使用ActionGroup来存储最低(0)的start_time和最高(13)的end_time,因为Action已经具有group_id,则可以使用

轻松获取start_time或end_time。
Select start_time in Action where group_id = '1' order by start_time;

然后ActionGroup根本没有目标,但是如果您想实现更多目标,那么我认为创建ActionGroup是个好主意。

例如:

  

有一个ActionGroup表,其中包含字段-id,start_time和   一组多个动作的结束时间(请注意,动作会发生   顺序)。

如果您有一个开始时间为4、8、2、2、10的动作,那么我们知道2将存储在ActionGroup中,但是Action是什么呢?然后,您可以执行类似start_time_id而不是start_time的操作。

以下是一些用于创建表格的阅读材料,可以帮助您:

HOW TO DESIGN A SQL DATABASE

Database Structure and Design Tutorial