数据库设计 - 类别和子类别

dsb*_*dsb 11 database sql-server categories database-performance

我需要对与黄金页面有点类似的东西实现分类和子分类.

假设我有下表:

分类表

CategoryId, Title
10, Home
20, Business
30, Hobbies
Run Code Online (Sandbox Code Playgroud)

我有两个选项来编码子分类.

选项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, ...
Run Code Online (Sandbox Code Playgroud)

选项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, ...
Run Code Online (Sandbox Code Playgroud)

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

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

SELECT BizTitle FROM tblBiz WHERE CatId = 30 AND SubCatId = 170
Run Code Online (Sandbox Code Playgroud)

即包含一个额外的 AND

但是,选项1更容易手动维护(当我需要更新和插入新的子类别等时,在我看来它更令人愉悦.

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

sla*_*dan 15

我会用这个结构:

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, ...
Run Code Online (Sandbox Code Playgroud)

详细地:

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

只要您只使用两个级别的类别,您仍然可以选择如下:

SELECT BizTitle FROM tblBiz WHERE ParentId = 3 AND CategoryId = 11
Run Code Online (Sandbox Code Playgroud)

hierarchyidSQL服务器的新功能看起来很有前途:https://msdn.microsoft.com/en-us/library/bb677173.aspx


我不喜欢嵌套集模型:

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


Vah*_*afi 7

管理分层数据有一些方法.其中最重要的一个是Nested Set Model.

请参阅此处以获取实施

甚至像joomla这样的内容管理系统也使用这种结构.

  • 2020年的解决方案简单明了。谢谢 (2认同)