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

How to avoid duplicate data in one-to-many relationship

考虑以下情况:

有一个 Action table,它有字段 - idstart_timeend_timegroup_id

有一个 ActionGroup table,其中包含一组多个操作的字段 - idstart_timeend_time(请注意动作顺序发生)。

ActionGroupAction.

具有一对多关系

例如:

如果有四条Action条记录,

相关的 ActionGroup 记录看起来像


好像Actiontable已经包含了ActionGrouptable需要的数据,ActionGroup其实是在重复

是否可以以一种简单且高效的方式查询 ActionGroup 的开始时间和结束时间,而无需单独记录 ActionGroup 中的 start_timeend_time 字段]?

此外,在设计 table 架构时,像上述情况一样复制数据是否被认为是一种不好的做法?

It seems that Action table already includes the data that ActionGroup table needs, and ActionGroup is actually repeating it.

我认为你是对的,你只是在根据你的例子重复它。如果你只是用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.

是个好主意

例如:

there is an ActionGroup table, which has fields - id, start_time and end_time of a group of multiple actions(Please note that actions occur sequentially).

如果您的操作带有 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

从你的最后一个问题开始:数据重复是不好的,因为它会带来不一致的风险,例如如果您的 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 相关变量 (table) 中的那些属性。这很简单;是否足够快取决于您的要求。

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

I don't think you need ActionGroup table from your example

根据您的示例 Action table 已经拥有 ActionGroups 的所有信息(group_id、start_time、end_time)

您可以只使用 Action table 来获取 start_time 和 end_time 的最小值和最大值,但是如果您需要 ActionGroup 上的更多字段并获取组的操作的 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