树形结构在后端系统中非常常见,特别是分类管理场景,例如商品分类、组织架构等。本文将以给定的数据库表为例,探讨如何设计树结构分类数据模型及其优点。
CREATE TABLE `product_classification_node` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键(分类ID)',
`classification_name` varchar(50) NOT NULL DEFAULT '' COMMENT '分类名称',
`parent_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '分类父ID',
`classification_desc` varchar(511) NOT NULL DEFAULT '' COMMENT '分类描述',
`is_enabled` tinyint(1) NOT NULL DEFAULT '-1' COMMENT '是否启用 | 0:未启用 1:启用',
`create_user_id` varchar(50) NOT NULL DEFAULT '' COMMENT '创建用户id',
`create_user_name` varchar(20) NOT NULL DEFAULT '' COMMENT '创建用户姓名',
`update_user_id` varchar(50) NOT NULL DEFAULT '' COMMENT '更新用户id',
`update_user_name` varchar(20) NOT NULL DEFAULT '' COMMENT '更新用户姓名',
`time_update` bigint(20) NOT NULL COMMENT '更新时间',
`time_create` bigint(20) NOT NULL COMMENT '创建时间',
`product_count` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name_pid` (`parent_id`,`classification_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类节点表';
该表主要记录分类的基本信息和层级关系,通过parent_id
字段表示父子关系。
CREATE TABLE `product_classification_node_closure` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`descendant_id` bigint(20) NOT NULL COMMENT '后代节点 ID',
`ancestor_id` bigint(20) NOT NULL COMMENT '祖先节点 ID',
`depth` tinyint(3) NOT NULL COMMENT '祖先节点到后代节点的层数差',
`time_update` bigint(20) NOT NULL COMMENT '更新时间',
`time_create` bigint(20) NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_ancestorid_descendantid` (`ancestor_id`,`descendant_id`),
KEY `k_descendantid` (`descendant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类节点闭包表';
闭包表记录了每个节点与其所有祖先和后代的关系,depth
字段表示层级差。
CREATE TABLE `classification_product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`productclassificationnode_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT '分类表主键ID',
`product_id` bigint(20) NOT NULL DEFAULT '-1' COMMENT 'product 表主键ID',
`product_code` int(11) NOT NULL DEFAULT '-1' COMMENT '商品编码',
`create_user_id` varchar(50) NOT NULL DEFAULT '' COMMENT '创建用户id',
`create_user_name` varchar(20) NOT NULL DEFAULT '' COMMENT '创建用户姓名',
`update_user_id` varchar(50) NOT NULL DEFAULT '' COMMENT '更新用户id',
`update_user_name` varchar(20) NOT NULL DEFAULT '' COMMENT '更新用户姓名',
`time_update` bigint(20) NOT NULL COMMENT '更新时间',
`time_create` bigint(20) NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_procutid_nodeid` (`product_id`,`productclassificationnode_id`),
KEY `k_productclassificationnodeid_areazip` (`productclassificationnode_id`,`area_zip`),
KEY `k_productcode_areazip` (`product_code`,`area_zip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类商品表';
此表实现商品与分类节点的关联,支持快速查询商品所属分类。
product_classification_node
中,通过parent_id
实现父子节点关系。数据插入时即可构建树状结构。product_classification_node_closure
闭包表,便于快速查询某一节点的所有祖先或后代,优化层级遍历性能。UNIQUE KEY
保证数据唯一性,防止重复插入。ancestor_id
、descendant_id
,支持多级分类的高效查询。classification_product
表支持商品与分类多对多关系管理,灵活应对商品多分类场景。uk_procutid_nodeid
和k_productclassificationnodeid_areazip
便于快速定位商品分类和地域维度。获取分类树:
SELECT * FROM product_classification_node
WHERE is_enabled = 1;
parent_id
递归构建树。查询某分类的所有后代:
SELECT descendant_id FROM product_classification_node_closure
WHERE ancestor_id = ?;
查询某分类的所有祖先:
SELECT ancestor_id FROM product_classification_node_closure
WHERE descendant_id = ?;
统计分类下商品数量:
SELECT SUM(product_count) FROM product_classification_node_closure c
JOIN product_classification_node n ON c.descendant_id = n.id
WHERE c.ancestor_id = ?;
通过这样的设计,不仅能够满足树结构数据模型的基本需求,还具备良好的性能和扩展性,适合于复杂的后端分类管理场景。