zoukankan      html  css  js  c++  java
  • 【SQL / MySQL】Hierarchical Queries (层级结构查询)

    @

    Hierarchical Queries

    层级结构是表达数据的一种重要关系,在数据库设计中,如:组织机构、行政区划、菜单目录 等 都是层次关系数据的典型实例。设计方案总的来说主要是两大类。

    ID/PID 设计方案

    1. 原理 :增加 parent_id 属性,存储父节点的 id ;也可增加 path 属性,存储 节点路径,优化设计;
    2. 实现
      ① FUNCTION
    # 查询上级节点 (FUNCTION)
    CREATE FUNCTION `f_getParents`(root_id BIGINT) RETURNS varchar(16384)
    BEGIN
      DECLARE pTemp VARCHAR(16384) DEFAULT '$';
      DECLARE cTemp INT DEFAULT 1;
      WHILE root_id > 0 DO
        SET cTemp = (SELECT ${PID} FROM ${TABLE_NAME} WHERE ${ID} = 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}, f_getParents(#{id}));
    
    # 查询下级节点 (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}) INTO cTemp FROM ${TABLE_NAME} WHERE FIND_IN_SET(${PID}, cTemp) > 0;
        SET idx = idx + 1;
      END WHILE;  
      RETURN pTemp;  
    END;
    # 调用 f_getChildren
    SELECT * FROM ${TABLE_NAME} WHERE FIND_IN_SET(${ID}, f_getChildren(#{id}));
    

    ② SQL

    # 查询上级节点 (SQL)
    SELECT t1.*, t2.c_lv FROM ${TABLE_NAME} t1, (
      SELECT
        @id as c_id,
        (SELECT @id := ${PID} FROM ${TABLE_NAME} WHERE ${ID} = @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, id;
    
    # 查询下级节点 (SQL)
    SELECT t1.*, t2.c_lv FROM ${TABLE_NAME} t1, (
      SELECT
        @ids AS c_ids,
        (SELECT @ids := GROUP_CONCAT(${ID}) FROM ${TABLE_NAME} WHERE FIND_IN_SET(${PID}, @ids)) AS c1,
        @lv := @lv + 1 AS c_lv
      FROM ${TABLE_NAME}, (SELECT @ids := #{pid}, @lv := 0) vars
      WHERE @ids IS NOT NULL
    ) t2 WHERE FIND_IN_SET(t1.id, t2.c_ids) AND t1.id <> #{pid}
    ORDER BY c_lv, id;
    

    左右值 设计方案

    1. 原理 :类似前序遍历,先访问父节点,再访问子节点,递增标记,每个节点访问两次,分左(lft)右(rgt)值;也可增加 level / layer 属性,储存节点的深度,优化设计;
    2. 实现 :此方案资料较多,随机列出一些供参考
      左右值编码树形结构数据存储方案
      MySQL多层级结构-树搜索
      采用左右值编码实现无限分级树形结构
  • 相关阅读:
    mysql操作
    Linux内核事件通知链学习
    C++双端队列学习
    tune的结果图是什么
    conda环境备份
    Could not load dynamic library 'libcudart.so.11.0';
    Unexpected error while saving file: xxx.ipynb database or disk is full
    友元函数与友元类
    构造函数初始化必须采用初始化列表的情况
    模型集成04-GMM
  • 原文地址:https://www.cnblogs.com/zhuzhongxing/p/14528894.html
Copyright © 2011-2022 走看看