我是否应该将所有MySQL表相互关联?

我是否应该将所有MySQL表相互关联?,mysql,sql,database-design,Mysql,Sql,Database Design,我正在做一个个人项目,负责各种项目的计时,但我不确定构建数据库的最佳方式 结构的简化分解如下所示: 每个客户端可以有多个报告 每个报表可以有多个行项目 每个行项目可以有多个时间记录 最终会有更多的关系,但这是应用程序的基础。如您所见,每个项目都以一对多的关系与其下的项目相关 我的问题是,我应该将每个表与上面的每个“父”表关联起来吗?大概是这样的: clients id reports id client_id line_items id repor

我正在做一个个人项目,负责各种项目的计时,但我不确定构建数据库的最佳方式

结构的简化分解如下所示:

  • 每个客户端可以有多个报告
  • 每个报表可以有多个行项目
  • 每个行项目可以有多个时间记录
最终会有更多的关系,但这是应用程序的基础。如您所见,每个项目都以一对多的关系与其下的项目相关

我的问题是,我应该将每个表与上面的每个“父”表关联起来吗?大概是这样的:

clients
    id

reports
    id
    client_id

line_items
    id
    report_id
    client_id

time_records
    id
    report_id
    line_item_id
    client_id
Client
    ClientId

Report
    ReportId
    ClientId

LineItem
    LineItemId
    ReportId

TimeRecord
    TimeRecordId
    LineItemId
随着它的级联,将有越来越多的外键添加到每个新表中


我最初的反应是,这不是正确的方法,但我希望得到一些第二(和第三)种意见。

作为个人意见,我会:

clients
    id

time_records
    id
    client_id
    report
    line_item
    report_id
这样,您的所有字段都在
时间记录表中。然后,您可以执行以下操作:

SELECT *
FROM 'time_records'
WHERE 'time_records'.'client_id' = 16542
   AND 'time_records'.'report' = 164652
ORDER BY 'time_records'.'id' ASC

不,如果模型的元素中没有直接关系,那么相应的表中就不应该有直接关系。否则,您的数据将有冗余,并且您将在更新时遇到问题

这是正确的方法:

clients
    id

reports
    id
    client_id

line_items
    id
    report_id

time_records
    id
    line_id

如果从不直接连接行项目客户端,则不需要在
行项目
表上创建
客户端id
,因为您可以通过
报告
表获得该id。其他FK也是如此

我建议您在创建可能使开发复杂化的冗余外键之前,在报告中考虑对该数据集合的需求/查询

如果将来需要,创建冗余FK并不困难,一些更改和更新选择可以解决您的问题


如果您在
行\u项中没有那么多信息
,您可以在
时间\u记录中取消规范化并添加此信息

这样做的好处是,您可以检查所有时间记录,例如,特定的客户端id,而无需加入。但事实上,这是没有必要的。您只需将引用存储到一个“级别”即可。以下是“客户”视角下的一些示例:

获取特定客户的报告:(简单;与您建议的当前模式相同)

获取特定客户端的行项目:(新架构;不需要表中的“客户端id”)

获取特定客户端的时间项:(新架构;不需要表中的“客户端id”或“报告id”)

因此,修改后的模式为:

clients
    id

reports
    id
    client_id

line_items
    id
    report_id

time_records
    id
    line_item_id
编辑:

clients
    id

reports
    id
    client_id

line_items
    id
    report_id

time_records
    id
    line_item_id

另外,我会考虑使用视图来简化查询(我假设您经常使用它们),明确地在连接列上创建索引,并使用外键引用进行归一化(UnDB只)。

< P>在两个表之间有直接关系,应该使用外键来保持数据完整性。就我个人而言,我会考虑这样的结构:

clients
    id

reports
    id
    client_id

line_items
    id
    report_id
    client_id

time_records
    id
    report_id
    line_item_id
    client_id
Client
    ClientId

Report
    ReportId
    ClientId

LineItem
    LineItemId
    ReportId

TimeRecord
    TimeRecordId
    LineItemId
在本例中,您不需要
LineItem
中的
ClientId
,因为您通过
Report
表具有这种关系。在所有表中使用
ClientId
的主要缺点是,如果业务逻辑没有强制这些值的一致性(代码中有一个bug),那么如果基于

Report:
   ReportId = 3
   ClientId = 2
LineItem:
   LineItemId = 1
   ReportId = 3
   ClientId = 3
在上述情况下,如果您的查询通过
Report
,您将看到
ClientId=2
;如果您的查询通过
LineItem
,则很难确定哪个关系是正确的,以及错误在哪里

此外,我主张不要使用
id
列,而是使用更明确的名称来描述
id
的用途。(
ReportId
ClientId
)在我看来,这使得连接更容易阅读。例如:

SELECT COUNT(1) AS NumberOfLineItems
FROM Client AS c
INNER JOIN Report AS r ON c.ClientId = r.ClientId
INNER JOIN LineItem AS li ON r.ReportId = li.ReportId
WHERE c.ClientId = 12

在格式化查询时,我还将
=
更改为
=
。我希望这个改变是你想要的;如果不是,很抱歉。谢谢!它是。尝试的速度比我想象的要快。你(概念上)如何区分行项目和时间记录?行项目是某种任务吗?是的,行项目将是一项任务。例如,一个行项目可能会读为“Build Timekeing application”,它会有多个时间记录(这里30分钟,那里12分钟,等等),这些时间记录加起来等于在一个行项目上花费的总时间。鉴于此,我认为您当前的设计是完全可以接受的(减去子表中的额外ID)我希望我能接受所有的答案,但我觉得你的答案解释得非常透彻。非常感谢。