单个表或多个表用于层次结构数据

时间:2019-03-05 03:30:32

标签: django database postgresql database-design

我必须实现以下层次结构数据:

Category (id, name, url)
SubCategory (id, name, url)
SubSubCategory (id, name, url)

请注意,这是多对多关系。 EG:每个节点可以有多个父级或子级。没有流通关系(感谢上帝)。只有某些SubSubCategory可以属于多个SubCategory。

我的实现:为此,我使用单个表

Cat (id, type(category, subcategory, subsubcategory), name, url)
CatRelation (id, parent_id, child_id, pre_calculated_index for tree retrieval)

pre_calculated_index可以是修改后的预排序树遍历的 [12] 或实现中的路径的左右实现。 pre_calculated_index的计算是在将子级添加到一个节点时进行的,因此,当您检索一棵树时,只需要按此字段排序即可,避免进行递归查询。

无论如何,我的老板认为这种实现方式并不理想。他建议为每种类型的类别都有一个表,然后再有一个将它们链接起来的数据透视表:

Category (id, name, url)
SubCategory (id, name, url)
SubSubCategory (id, name, url)
Category_SubCategory(category_id, sub_category_id)
SubCategory_SubSubCategory(sub_category_id, sub_sub_category_id)

检索树时,只需联接所有表。他的论据是,稍后将某些属性添加到不需要的任何类别类型时,在单表实现中将字段设为null。由于pre_calculated_index是用代码计算的,因此可能会出错。

我应该跟随哪个?哪个性能更好?

我使用django和postgreSQL。

PS:有关我的pre_calculated_index实现的更多详细信息: 我为CatRelation添加一个路径(字符串,唯一,索引)值,而不是为每个节点左右移动:根节点将具有“ path ='”。 子节点添加到CatRelation后,将具有path = parent_path +'。因此,当您按此路径排序时,将按树顺序获得所有内容。例子:

Cat

| id | name       | url |
|----|------------|-----|
| 1  | Cat1       |     |
| 2  | Subcat1    |     |
| 3  | Subcat2    |     |
| 4  | Subcat3    |     |
| 5  | Subsubcat1 |     |
| 6  | Subsubcat2 |     |
| 7  | Subsubcat3 |     |

CatRelationship                                        Left right equivalent

| id    | parent_id     | child_id  | path      |           |lft |rght|            
|----   |-----------    |---------- |--------   |           |----|----|
| 1     | null          | 1         | 1.        |           | 1  | 14 |
| 2     | 1             | 2         | 1.2.      |           | 2  | 3  |
| 3     | 1             | 3         | 1.3.      |           | 4  | 11 |
| 4     | 1             | 4         | 1.4.      |           | 12 | 13 |
| 5     | 3             | 5         | 1.3.5.    |           | 5  | 6  |
| 6     | 3             | 6         | 1.3.6.    |           | 7  | 8  |
| 7     | 3             | 7         | 1.3.7.    |           | 9  | 10 |

因此,当您按路径排序(或在修改后的预排序树中按左顺序排序)时,您将获得这种不错的树结构,而无需递归:

| id    | parent_id     | child_id  | path      |
|----   |-----------    |---------- |--------   |
| 1     | null          | 1         | 1.        |
| 2     | 1             | 2         | 1.2.      |
| 3     | 1             | 3         | 1.3.      |
| 5     | 3             | 5         | 1.3.5.    |
| 6     | 3             | 6         | 1.3.6.    |
| 7     | 3             | 7         | 1.3.7.    |
| 4     | 1             | 4         | 1.4.      |

而且我总是可以使用递归动态构建路径:

WITH RECURSIVE CTE AS (
    SELECT R1.*, CONCAT(R1.id, ".") AS dynamic_path 
    FROM CatRelation AS R1
    WHERE R1.child_id = request_id
UNION ALL
    SELECT R2.*, CONCAT(dynamic_path, R2.child_id, ".") AS dynamic_path
    FROM CTE 
    INNER JOIN CatRelation AS R2 ON (CTE.child_id = R2.parent_id)      
)
SELECT * FROM CTE;

0 个答案:

没有答案