【问题标题】:Struggling with a data modeling problem努力解决数据建模问题
【发布时间】:2011-01-13 12:07:20
【问题描述】:

我正在为数据模型苦苦挣扎(我使用 MySQL 作为数据库)。我对自己的想法感到不安。如果有人可以提出更好的方法,或者向我指出一些参考资料,我将不胜感激。

数据将具有多种类型的组织。我正在尝试进行 3 级分类(类、类别、类型)。假设我有“意大利餐厅”,它将有以下分类

餐饮服务 > 餐厅 > 意大利菜

但是,一个组织可能属于多个组。餐厅也可能供应中餐和意大利菜。所以它将适合2个分类

餐饮服务 > 餐厅 > 意大利餐厅
餐饮服务 > 餐厅 > 中餐

分类参考表如下:

ORG_CLASS(RowId、ClassCode、ClassName)

1, FOOD, Food Services

ORG_CATEGORY(RowId, ClassCode, CategoryCode, CategoryName)

1, FOOD, REST, Restaurants

ORG_TYPE(RowId、ClassCode、CategoryCode、TypeCode、TypeName)

100, FOOD, REST, ITAL, Italian
101, FOOD, REST, CHIN, Chinese
102, FOOD, REST, SPAN, Spanish
103, FOOD, REST, MEXI, Mexican
104, FOOD, REST, FREN, French
105, FOOD, REST, MIDL, Middle Eastern

实际的数据表如下所示:

我将允许一个组织最多 3 个分类。我将有 3 个 GroupId,每个指向 ORG_TYPE 中的一行。所以我有我的 ORGANIZATION_TABLE

ORGANIZATION_TABLE(OrgGroupId1、OrgGroupId2、OrgGroupId3、OrgName、OrgAddres)

100,103,NULL,MyRestaurant1, MyAddr1
100,102,NULL,MyRestaurant2, MyAddr2
100,104,105, MyRestaurant3, MyAddr3

在数据添加过程中,对话框可以让用户选择 clssa、类别、类型,并且可以使用 ORG_TYPE 表中的 rowid 填充相应的 GroupId。

在搜索过程中,如果三个分类都被选中,它会更具体。例如,如果

食品服务 > 餐厅 > 意大利是标准,where 子句将是 'where OrgGroupId1 = 100'

如果只选择 2 个级别

餐饮服务 > 餐厅

我必须做'where OrgGroupId1 in (100,101,102,103,104,105, .....)' - 该列表中可能有一百个

我将禁止类级别搜索。那就是我会强制选择一个类和类别

ID 将是整数。我正在尝试查看性能问题和其他问题。

总的来说,这行得通吗?或者我需要把它扔掉,从头开始。

【问题讨论】:

  • 这对于您的目的来说可能有点矫枉过正,但是一篇关于管理分层数据的好文章:dev.mysql.com/tech-resources/articles/hierarchical-data.html
  • 感谢您的链接。这确实是一个很好的参考。它确实让我有另一个分类选择。文中的这种方式比较灵活,不限制分类的层数。
  • @trickwallet:该地址不再提供该文章。现在在这里:mikehillyer.com/articles/managing-hierarchical-data-in-mysql
  • 实际上,我最终得到了一种数据模式,与文章中推荐的分层数据结构一致。我希望这篇文章可以作为任何想要建立分层数据模型的人的参考。感谢您发布文章的新位置。

标签: datamodel database-design


【解决方案1】:

我不喜欢“最多三个”分类的三列。在我看来,最好有一个交叉引用表,允许您在组织和类型之间进行多对多映射,即表 ORGANISATION_GROUPS 与列 OrganisationId、OrgGroupId。

要解决能够查询指定的不同分类级别的问题,您可以设置此交叉引用表来保存实际分类,即 ORGANISATION_GROUPS 具有列:OrganisationId、ClassCode、CategoryCode、TypeCode。

这将使不同分类级别的查询变得非常容易。

为了使用此方案的引用完整性,我建议不要对 ORG_* 表使用代理整数键,而是将主键设置为真正的唯一键,即 ORG_TYPE 的 ClassCode、CategoryCode、TypeCode。

【讨论】:

  • 感谢您的帮助。甚至我也觉得需要一个交叉引用表。但是,我正在使用现有的软件,如果一切都在一张桌子上,这种软件效果很好。该应用程序目前并不太复杂。因此,我曾想过将分类放在数据表本身中。如果我必须扩大规模,我也许可以将分类移出数据表并创建交叉引用表。我正在尝试看看是否可以推迟对现有软件的重大更改。
【解决方案2】:

我在您的设计中看到的问题是它有点死板。以下是您可能要考虑的更灵活的方法:

首先,您将有一个用于类、类别、类型和任何其他分类类型的表。该表将被自动引用。所有寄存器都会有一个引用其直接父级的字段,如下所示:

分类(ID、描述、Parent_Id)

ITAL, Italian, REST
CHIN, Chinese, REST
MEXI, Mexican, REST
REST, Restaurant, FOOD

接下来,正如@John Pickup 建议的那样,您将拥有一个介于您的餐厅(或任何您需要的)表和分类表之间的中间交叉引用表,该表将仅包含一个复合主键,作为其组件的主键两张表。

FOODSERVICE_CLASSIFICATION(Rest_Id、Class_Id)

100, ITAL
100, CHIN
101, MEXI
102, CHIN

建议限制它,以便在交叉引用表中只能引用 CLASSIFICATION 表的叶寄存器。

您查找所有餐馆的示例就像查找 REST 的所有子类别并在交叉引用表中搜索它们一样简单。这可以写在 Oracle 中的单个选择中(不确定其他 RDBMS)。

这样你可以:

  • 为您的餐厅提供多种分类,但不限于 3 个类别。
  • 使用交叉引用表进行快速搜索。

请注意,假设您的分类就像一棵以基本类别作为根的树,则此架构会起作用。相反,如果您需要更松散的分类,您可能需要使用标签方法。

顺便说一句,我也同意@John Pickup 在这种情况下最好使用真正的主键。

HTH

【讨论】:

  • 感谢您的帮助。我将尝试找出您的建议,看看我是否可以提出一个模型。我可以只使用建议的层次结构。我正在使用现有软件,如果我要使用交叉引用表,可能需要更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多