@
目录
- Hierarchical Queries
- ID/PID 设计方案
- 左右值 设计方案
层级结构是表达数据的一种重要关系,在数据库设计中,如:组织机构、行政区划、菜单目录 等 都是层次关系数据的典型实例。设计方案总的来说主要是两大类。
ID/PID 设计方案- 原理 :增加 parent_id 属性,存储父节点的 id ;也可增加 path 属性,存储 节点路径,优化设计;
- 实现 :
① FUNCTION
# 查询上级节点 (FUNCTION) CREATE FUNCTION `f_getParents`(root_id BIGINT) RETURNS varchar(16384) BEGIN DECLARE pTemp VARCHAR(16384) DEFAULT '$'; DECLARE cTemp BIGINT DEFAULT 1; WHILE root_id > 0 DO SET cTemp = (SELECT ${PID_NAME} FROM ${TABLE_NAME} WHERE ${ID_NAME} = root_id); IF cTemp > 0 THEN SET pTemp = CONCAT(pTemp, ',', cTemp); END IF; SET root_id = cTemp; END WHILE; RETURN pTemp; END; # 调用 f_getParents -- SELECT * FROM ${TABLE_NAME} WHERE FIND_IN_SET(${ID_NAME}, f_getParents(#{id})); SELECT t0.* FROM ${TABLE_NAME} t0, (SELECT f_getParents(#{id}) c_ids) t1 WHERE FIND_IN_SET(${ID_NAME}, c_ids); # 查询下级节点 (FUNCTION) CREATE FUNCTION `f_getChildren`(root_id BIGINT) RETURNS varchar(16384) BEGIN DECLARE pTemp VARCHAR(16384) DEFAULT '$'; DECLARE cTemp VARCHAR(16384); DECLARE idx INT DEFAULT 0; SET cTemp = CAST(root_id AS CHAR); WHILE cTemp IS NOT NULL DO IF idx > 0 THEN SET pTemp = CONCAT(pTemp, ',', cTemp); END IF; SELECT GROUP_CONCAT(${ID_NAME}) INTO cTemp FROM ${TABLE_NAME} WHERE FIND_IN_SET(${PID_NAME}, cTemp) > 0; SET idx = idx + 1; END WHILE; RETURN pTemp; END; # 调用 f_getChildren -- SELECT * FROM ${TABLE_NAME} WHERE FIND_IN_SET(${ID_NAME}, f_getChildren(#{id})); SELECT t0.* FROM ${TABLE_NAME} t0, (SELECT f_getChildren(#{id}) c_ids) t1 WHERE FIND_IN_SET(${ID_NAME}, c_ids);
② SQL
# 查询上级节点 (SQL) SELECT t1.*, t2.c_lv FROM ${TABLE_NAME} t1, ( SELECT @id as c_id, (SELECT @id := ${PID_NAME} FROM ${TABLE_NAME} WHERE ${ID_NAME} = @id) as c_pid, @lv := @lv - 1 AS c_lv FROM ${TABLE_NAME}, (SELECT @id := #{id}, @lv := 0) vars WHERE @id > 0 ) t2 WHERE t2.c_id = t1.id AND t1.id <> #{id} ORDER BY c_lv, ${PID_NAME}, ${ID_NAME}; # 查询下级节点 (SQL) SELECT t1.*, t2.c_lv FROM ${TABLE_NAME} t1, ( SELECT @ids AS c_ids, (SELECT @ids := GROUP_CONCAT(${ID_NAME}) FROM ${TABLE_NAME} WHERE FIND_IN_SET(${PID_NAME}, @ids)) AS c1, @lv := @lv + 1 AS c_lv FROM ${TABLE_NAME}, (SELECT @ids := #{id}, @lv := 0) vars WHERE @ids IS NOT NULL ) t2 WHERE FIND_IN_SET(t1.id, t2.c_ids) AND t1.id <> #{id} ORDER BY c_lv, ${PID_NAME}, ${ID_NAME};左右值 设计方案
- 原理 :类似前序遍历,先访问父节点,再访问子节点,递增标记,每个节点访问两次,分左(lft)右(rgt)值;也可增加 level / layer 属性,储存节点的深度,优化设计;
- 实现 :此方案资料较多,随机列出一些供参考
① 左右值编码树形结构数据存储方案
② MySQL多层级结构-树搜索
③ 采用左右值编码实现无限分级树形结构
评论列表