当前位置: 首页 > 知识库问答 >
问题:

mysql树形结构数据筛选,叶子结点处理,如何筛选出预期数据?

姜良哲
2024-02-21

mysql树形结构筛选
mysql版本:5.7
有如下结构:

CREATE TABLE tb_tree (      id INT NOT NULL PRIMARY KEY,      pid INT not null default 0,      full_path VARCHAR(255) NULL,      FOREIGN KEY (pid) REFERENCES tb_tree(id)  );

id:主键ID
pid:树形结构,标识当前行的父节点ID
full_path:当前行在树形结构中的路径,例如当前id为10,父节点为9,那么他的full_path为:9-10

例如在经过某一轮筛选后,有如下数据,或者说某个账号只能看到如下数据

注意ID为100的数据,它的父节点99是存在的,只是业务逻辑中无法得到该节点的数据
INSERT INTO tb_tree (id, pid, full_path) VALUES (1, 0, '1');INSERT INTO tb_tree (id, pid, full_path) VALUES (2, 1, '1-2');INSERT INTO tb_tree (id, pid, full_path) VALUES (3, 2, '1-2-3');INSERT INTO tb_tree (id, pid, full_path) VALUES (4, 3, '1-2-3-4');INSERT INTO tb_tree (id, pid, full_path) VALUES (100, 99, '99-100');INSERT INTO tb_tree (id, pid, full_path) VALUES (101, 99, '99-100-101');INSERT INTO tb_tree (id, pid, full_path) VALUES (201, 200, '200-201');

现在有如下需求:

  1. 如果存在根节点的数据,那么这个根节点的所有叶子结点都忽略,只保留根节点,如上面id为1,2,3,4的数据,因为2,3,4都是1的叶子结点,因此只筛选出id为1的数据
  2. id为100,101,根节点没有出现在数据中,因此保留当前出现的最顶级节点,但是其叶子结点都忽略
    image.png
    image.png
  3. 尝试先将pid=0也就是根节点的数据先取出来,然后筛选,但是因为整个节点还有分支,貌似5.7不支持两个集合取交集

共有1个答案

郑安晏
2024-02-21

在MySQL 5.7中,要解决这个问题,我们可以使用递归查询。由于MySQL 5.7不支持公共表表达式(CTE),我们需要使用一个存储过程来实现递归。以下是一个可能的解决方案:

首先,我们需要创建一个存储过程来处理这个问题。这个存储过程将遍历树形结构,找到所有的根节点,然后找到每个根节点的所有叶子节点。然后,我们可以从这些叶子节点中筛选出我们需要的节点。

DELIMITER //CREATE PROCEDURE GetTreeNodes(IN root_id INT)BEGIN    -- 声明变量    DECLARE done INT DEFAULT FALSE;    DECLARE cur_id INT;    DECLARE cur CURSOR FOR SELECT id FROM tb_tree WHERE pid = root_id;    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;    -- 打开游标    OPEN cur;    -- 循环遍历每个子节点    read_loop: LOOP        FETCH cur INTO cur_id;        IF done THEN            LEAVE read_loop;        END IF;        -- 如果当前节点是叶子节点,则输出其信息        IF (SELECT COUNT(*) FROM tb_tree WHERE full_path LIKE CONCAT(root_id, '-%') AND pid != root_id) = 0 THEN            SELECT * FROM tb_tree WHERE id = cur_id;        ELSE            -- 如果当前节点不是叶子节点,则递归处理其子节点            CALL GetTreeNodes(cur_id);        END IF;    END LOOP;    -- 关闭游标    CLOSE cur;END //DELIMITER ;

然后,你可以通过调用这个存储过程来获取你需要的节点。例如,如果你想获取根节点为1的所有节点,你可以这样做:

CALL GetTreeNodes(1);

这个存储过程将返回所有根节点为1的叶子节点。注意,这个解决方案假设每个节点在full_path中只出现一次。如果一个节点可能在full_path中出现多次,你可能需要修改这个存储过程以正确地处理这种情况。

 类似资料:
  • 这一组数据在进行groupby前已经完成筛选,但进行groupby聚合后的结果显示是利用未筛选的数据进行的聚合,就像下面的结果,在groupby前已经完成点击量非0过滤,但最后仍存在含0的资源,询问chatGPT给的方案是可能用索引前的数据进行的聚合,重置索引后仍无法解决,请教大牛是否遇到过类似的问题,虽然可以在聚合后重新进行filter过滤,但这个问题搞得很焦灼 代码源文本

  • 选择数据表格头部 图标,可以选择表格内字段进行复杂条件筛选; 筛选结果在表格内显示; 选择: 选择图层内字段名称 约束条件: 对选择的该字段指定条件,条件一般有等于、小于、大于等(数值型字段)、或者包含、不包含等(文本型字段)... 约束值:输入需要限制的值 可以支持多种条件同时筛选、或者任选其一条件满足;

  • 问题内容: 您可以在不使用ThreadLocal或HttpSession的情况下将一些数据从javax.servlet.Filter传递到Jersey端点吗? 因为第一个问题是“您为什么要这样做?”:大多是好奇的。实际上,我认为我可以使用它来将身份验证过程中生成的一些数据传递给端点。不使用ThreadLocal消除了在链下使用它的诱惑(希望没有必要解释为什么这是邪恶的),并且不使用HttpSess

  • 本文向大家介绍Python如何用filter函数筛选数据,包括了Python如何用filter函数筛选数据的使用技巧和注意事项,需要的朋友参考一下 一.filter函数简介 filter函数主要用来筛选数据,过滤掉不符合条件的元素,并返回一个迭代器对象,如果要转换为列表list或者元祖tuple,可以使用内置函数list() 或者内置函数tuple()来转换; filter函数接收两个参数,第一个

  • 树形结构有两种表示方法:子表表示法(嵌套)和父指针表示法(扁平)。 Tree 将两者进行了整合,输出一个扁平的结构,一个节点既通过 pId(指向父节点的唯一标志)建立与父节点关系,又通过 children(数组,存储子节点的唯一标志)建立与子节点的关系。 一个树形结构,为了方便处理,通常需要具备以下特点: 一个扁平的数组结构很重要,在需要获取某个节点时,可以仅通过一次循环快速找到该节点。Tree

  • 若要用单个列过滤数据文件(DF),如果我们考虑有男性和女性的数据,我们可以: 问题1——但如果数据跨越多年,而我只想看到2014年的男性会怎样? 在其他语言中,我可能会这样做: (除非我想这样做并在新的dataframe对象中获取原始dataframe的子集) 问题2。我如何在一个循环中实现这一点,并为每个独特的年份和性别集(即:2013年男性、2013年女性、2014年男性和2014年女性)创建