【问题标题】:database design - categories and sub-categories [closed]数据库设计 - 类别和子类别
【发布时间】:2015-10-15 21:30:40
【问题描述】:

我需要在有点类似于金页的东西上实现分类和子分类。

假设我有下表:

分类表

CategoryId, Title
10, Home
20, Business
30, Hobbies

我有两个选项来编码子类别。

选项 1 - 子类别 ID 仅在类别中是唯一的:

子类别表

CategoryId, SubCategoryId, Title
10, 100, Gardening
10, 110, Kitchen
10, 120, ...
20, 100, Development
20, 110, Marketing
20, 120, ...
30, 100, Soccer
30, 110, Reading
30, 120, ...

选项 2 - 子类别 ID 总体上是唯一的:

子类别表

CategoryId, SubCategoryId, Title
10, 100, Gardening
10, 110, Kitchen
10, 120, ...
20, 130, Development
20, 140, Marketing
20, 150, ...
30, 160, Soccer
30, 170, Reading
30, 180, ...

选项 2 听起来更容易从表中获取行 例如:SELECT BizTitle FROM tblBiz WHERE SubCatId = 170

而使用选项 1 我必须写这样的东西:

SELECT BizTitle FROM tblBiz WHERE CatId = 30 AND SubCatId = 170

即包含一个额外的AND

但是,选项 1 更易于手动维护(当我需要更新和插入新的子类别等时,我认为它更令人赏心悦目。

对此有什么想法吗?选项 2 在效率方面值得麻烦吗?是否有与此常见问题相关的设计模式?

【问题讨论】:

  • 我认为您必须使用选项 2 为 categoryid 为 PK 的类别制作一个表,并在 subcategoryid 为 PK 且 categoryid 为 FK 的情况下制作另一个表 SubCategory

标签: sql-server database categories database-performance


【解决方案1】:

我会使用这个结构:

ParentId, CategoryId, Title
null, 1, Home
null, 2, Business
null, 3, Hobbies
1, 4, Gardening
1, 5, Kitchen
1, 6, ...
2, 7, Development
2, 8, Marketing
2, 9, ...
3, 10, Soccer
3, 11, Reading
3, 12, ...

详细说明:

  • 只使用一张表,引用自己,这样你就可以拥有无​​限的类别深度
  • 使用技术ID(使用IDENTITY,或类似的),这样您就可以拥有超过10个子类别
  • 如果需要,为类别编号添加一个人类可读列作为单独的字段

只要您只使用两个级别的类别,您仍然可以像这样选择:

SELECT BizTitle FROM tblBiz WHERE ParentId = 3 AND CategoryId = 11

SQL Server 的hierarchyid 新功能看起来也很有前景:https://msdn.microsoft.com/en-us/library/bb677173.aspx


我不喜欢 嵌套集模型

  • 嵌套集模型插入和删除项是一件相当复杂的事情,需要昂贵的锁。
  • 如果您将parent 字段与外键约束结合使用,则可以轻松创建被禁止的不一致
    • 如果rght 低于 低于lft,则可能出现不一致
    • 如果一个值出现在多个 rghtlft 字段中,则可能会出现不一致
    • 如果您创建差距,可能会出现不一致
    • 如果创建重叠,可能会出现不一致
  • 在我看来,嵌套集模型复杂,因此不太容易理解。当然,这绝对是主观的。
  • 嵌套集模型需要两个字段,而不是一个 - 因此会占用更多磁盘空间。

【讨论】:

  • 在这种情况下,每次我们必须应用自我加入来获得我们的类别与子类别是否可行
  • @tinka 如果您只使用两个深度级别,您仍然可以轻松选择(请参阅我的更新)
  • 我无法下定决心。但我接受了你的建议。感谢所有试图提供帮助的人。
  • 你真的应该了解嵌套集模型。这个答案并不总是解决这类问题的最佳方法。
  • @slartidan 归根结底这是个人喜好问题。
【解决方案2】:

管理分层数据有一些方法。最重要的之一是Nested Set ModelSee here 用于实施。甚至像 Joomla 这样的一些内容管理系统,也使用这种结构。

2020 年更新:由于这篇文章有一些注意事项,我应该说现在我更喜欢邻接表模型而不是嵌套集模型,因为这种方式的复杂性较低。也可以See here 执行。

【讨论】:

    【解决方案3】:

    我建议使用 选项 1 - 使子类别在类别中保持唯一。假设我有两类不相关的项目:

    • 水果
    • 颜色

    对于每个我想要一个子类别

    • 水果

      • 苹果
      • 橙色
    • 颜色

      • 白色
      • 橙色

    请注意,Orange 是每个类别中的一个子类别。虽然名称相同,但功能却大相径庭。 (让我们不要讨论橙色水果是橙色的可能性)

    有了这个设计,如果有人改变主意,想把 Orange 重命名为 Oranges,没问题。在不影响颜色下的橙色子类别的情况下轻松更改。

    如果您的 UI 以这样一种方式构建,即 Marketing 可以控制 Colors 的子类别,而 Production 可以控制 Fruits 的子类别,则此设计将允许 Marketing 使用其子类别而无需跨过 Production 的子类别。

    【讨论】:

      猜你喜欢
      • 2023-03-11
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      相关资源
      最近更新 更多