我需要实现分类和子分类的东西,这是有点类似于黄金页面.

假设我有下表:

Category Table

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

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

OPTION 1 - Subcategory Id is unique within Category ONLY:

Sub Category Table

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, ...

OPTION 2 - Subcategory Id is unique OVERALL:

Sub Category Table

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更容易手动维护(当我需要更新和插入新的子类别等时),在我看来,它更令人赏心悦目.

有什么 idea 吗?就效率而言,选项2值得麻烦吗?有没有与这个常见问题相关的设计模式?

推荐答案

我会使用这种 struct :

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, ...

详细内容:

  • 只用一张表,其中references itself张,这样你就可以有无限深度的分类
  • 使用technical ids(使用IDENTITY或类似用法),这样您就可以有10个以上的子类别
  • 如果需要,为类别编号添加human readable列作为separate field

只要你只使用两个级别的类别,你仍然可以这样 Select :

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

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


我不喜欢Nested Set Model强的原因是:

  • Nested Set Model中的Inserting and deleting件物品非常复杂,需要昂贵的锁.
  • One can easily create inconsistencies which is prohibited, if you use the parent field in combination with a foreign key constraint.
    • 如果rghtlft等于lower,则可能出现不一致
    • 如果值apprears in severalrghtlft为字段,则可能会出现不一致
    • 如果创建gaps,可能会出现不一致
    • 如果创建overlaps,则可能会出现不一致
  • 在我看来,Nested Set Modelcomplex多,因此不那么容易理解.当然,这绝对是主观的.
  • Nested Set Model需要两个字段,而不是一个,因此需要更多的磁盘空间.

Database相关问答推荐

如果我想支持我的工作负载,我需要多少个 node ?

我们可以在 CnosDB 中的单个数据库中创建的标签数量是否有限制?

utf-8 与 latin1

术语 SSTable 和 LSM Tree 有什么区别

Spring DriverManagerDataSource vs apache BasicDataSource

数据库设计 - 类别(categories)和子类别(sub-categories)

如何打印出 sequelize 实例的表名?

Objective-C中是否有类似于LINQ的东西?

PostgreSQL - 按时间戳值分组?

为什么 DynamoDB 查询中没有**not equal**比较?

我们如何保存在 sqlite3 中创建的数据库

当另一个进程修改数据库时Hibernate二级缓存失效

在 SQLite 数据库中加入 3 个表

如何处理数据库中用户的身份验证/授权?

日期格式的 Oracle SQL 查询

如何在数据库中获取原始的created_at值(不是转换为 ActiveSupport::TimeWithZone 的对象)

Django:检测数据库后端

如何更正此 sql 连接上的相关名称?

Hibernate hbm2ddl.auto 默认值

最佳事件采购数据库策略