根据用户ID获取所有子节点数据或是上级直属节点数据

一、根据用户ID获取所有子节点,通过存储过程来实现

CREATE DEFINER=`crmeb`@`%` PROCEDURE `proc_get_user_all_children`(
    IN rootUid INTEGER,              -- 要查询的根用户ID
    IN includeSelf BOOLEAN      -- 是否包含自身(1=包含,0=不包含)
)
BEGIN

    
    -- 声明变量 
    DECLARE current_level INT DEFAULT 0;
    
    -- 创建临时表存储最终结果
    DROP TEMPORARY TABLE IF EXISTS final_result;
    CREATE TEMPORARY TABLE final_result (
        id INT PRIMARY KEY,
        level INT COMMENT '层级深度',
        spread_uid INT COMMENT '直接上级ID'
    ) ENGINE=InnoDB;
    
    -- 创建临时表存储当前层级的用户 
    DROP TEMPORARY TABLE IF EXISTS current_level_users;
    CREATE TEMPORARY TABLE current_level_users (
        id INT PRIMARY KEY
    ) ENGINE=Memory;
    
    -- 创建临时表存储下一层级的用户 
    DROP TEMPORARY TABLE IF EXISTS next_level_users;
    CREATE TEMPORARY TABLE next_level_users (
        id INT PRIMARY KEY,
        spread_uid INT
    ) ENGINE=Memory;
    
    -- 初始化:添加根节点(如果选择包含自身)
    IF includeSelf THEN
        INSERT INTO final_result 
        SELECT id, 0, spread_uid 
        FROM eb_user 
        WHERE id = rootUid;
    END IF;
    
    -- 初始化当前层级(根节点的直接下级)
    INSERT INTO current_level_users
    SELECT id 
    FROM eb_user 
    WHERE spread_uid = rootUid AND id != IF(includeSelf, -1, rootUid);
    
    -- 将直接下级加入结果集 
    INSERT INTO final_result 
    SELECT u.id,  1, u.spread_uid 
    FROM eb_user u
    WHERE u.spread_uid  = rootUid AND u.id  != IF(includeSelf, -1, rootUid);
    
    -- 循环处理每一层级(广度优先遍历)
    WHILE EXISTS (SELECT 1 FROM current_level_users) DO
        SET current_level = current_level + 1;
        
        -- 清空下一层级临时表
        TRUNCATE TABLE next_level_users;
        
        -- 查找当前层级用户的直接下级
        INSERT INTO next_level_users 
        SELECT u.id,  u.spread_uid  
        FROM eb_user u 
        JOIN current_level_users c ON u.spread_uid  = c.id 
        WHERE u.id  NOT IN (SELECT id FROM final_result);
        
        -- 将新找到的子节点添加到结果表 
        INSERT INTO final_result 
        SELECT id, current_level + 1, spread_uid 
        FROM next_level_users;
        
        -- 准备处理下一层级
        TRUNCATE TABLE current_level_users;
        INSERT INTO current_level_users
        SELECT id FROM next_level_users;
    END WHILE;
    
    -- 返回最终结果
    SELECT 
        r.id, 
        u.real_name,               -- 假设表中有real_name字段
        r.level, 
        r.spread_uid, 
        p.real_name  AS parent_name -- 上级用户名
    FROM final_result r
    JOIN eb_user u ON r.id  = u.id 
    LEFT JOIN eb_user p ON r.spread_uid  = p.id  
    ORDER BY r.level,  r.id; 
    
    -- 清理临时表 
    DROP TEMPORARY TABLE IF EXISTS final_result;
    DROP TEMPORARY TABLE IF EXISTS current_level_users;
    DROP TEMPORARY TABLE IF EXISTS next_level_users;
END

测试结果,如下:

二、根据用户ID获取用户所有上级直属节点,用存储过程实现,如下:


 
CREATE PROCEDURE sp_get_user_parent_nodes(
    IN base_user_id INT,       -- 要查询的基础用户ID 
    IN include_self BOOLEAN    -- 是否包含自己(1=包含,0=不包含)
)
BEGIN 

    
    -- 创建临时结果表(优化结构)
    DROP TEMPORARY TABLE IF EXISTS user_parent_nodes;
    CREATE TEMPORARY TABLE user_parent_nodes (
        node_level INT NOT NULL COMMENT '节点层级(0=自己,1=直接上级...)',
        user_id INT NOT NULL,
        real_name VARCHAR(100),
        parent_id INT,
        is_root_node BOOLEAN DEFAULT FALSE,
        PRIMARY KEY (user_id),
        KEY idx_level (node_level)
    ) ENGINE=InnoDB;
    
    -- 变量初始化 
    SET @current_user := base_user_id;
    SET @current_level := 0;
    SET @continue := 1;
    
    -- 如果包含自己,先添加自己 
    IF include_self THEN 
        INSERT INTO user_parent_nodes 
        SELECT 
            0 AS node_level,
            id AS user_id,
            real_name,
            spread_uid AS parent_id,
            CASE WHEN spread_uid IS NULL THEN TRUE ELSE FALSE END AS is_root_node 
        FROM eb_user 
        WHERE id = base_user_id;
    END IF;
    
    -- 使用WHILE循环向上追溯 
    WHILE @continue = 1 DO 
        -- 获取当前用户的直接上级信息 
        INSERT INTO user_parent_nodes 
        SELECT 
            @current_level + 1 AS node_level,
            parent.id  AS user_id,
            parent.real_name, 
            parent.spread_uid  AS parent_id,
            CASE WHEN parent.spread_uid  IS NULL THEN TRUE ELSE FALSE END AS is_root_node 
        FROM eb_user current 
        JOIN eb_user parent ON current.spread_uid  = parent.id  
        WHERE current.id  = @current_user 
        ON DUPLICATE KEY UPDATE node_level = LEAST(node_level, @current_level + 1);
        
        -- 检查是否插入成功 
        IF ROW_COUNT() = 0 THEN 
            -- 没有上级,标记当前用户为根节点(如果是第一次处理)
            UPDATE user_parent_nodes 
            SET is_root_node = TRUE 
            WHERE user_id = @current_user AND is_root_node = FALSE;
            
            SET @continue := 0;
        ELSE 
            -- 获取新插入的上级ID 
            SELECT user_id INTO @current_user 
            FROM user_parent_nodes 
            WHERE node_level = @current_level + 1 
            LIMIT 1;
            
            -- 检查是否已存在(防止循环引用)
            IF @current_user IN (
                SELECT user_id FROM user_parent_nodes 
                WHERE node_level < @current_level + 1 
            ) THEN 
                SET @continue := 0;
            END IF;
            
            SET @current_level := @current_level + 1;
        END IF;
    END WHILE;
    
    -- 返回最终结果(按层级排序)
    SELECT 
        node_level AS '层级',
        user_id AS '用户ID',
        real_name AS '用户名',
        CASE 
            WHEN node_level = 1 THEN '直接上级'
            WHEN is_root_node THEN '顶级节点'
            ELSE CONCAT('第', node_level, '级上级')
        END AS '关系类型',
        parent_id AS '下级用户ID'
    FROM user_parent_nodes 
    WHERE node_level > 0 OR include_self = 1 
    ORDER BY node_level;
    
    -- 清理临时表 
    DROP TEMPORARY TABLE IF EXISTS user_parent_nodes;
END 

测试结果,如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理——数据的表示

2.1数据的表示 整理自Beokayy_ 1.进制转换 十六进制与二进制的转换 一位十六进制等于四位二进制 四位二进制等于一位十六进制 0x173A4C0001 0111 0011 1010 0100 1100 十六进制与十进制的转换 十六转十&#xff1a;每一位数字乘以相应的16的幂再相加 十转十六&#xff1a…

基于MATLAB-GUI图形界面的数字图像处理

基于MATLAB GUI的数字图像处理系统实现方案&#xff0c;包含常见图像处理功能。代码分为两部分&#xff1a;GUI界面设计和回调函数实现。 %% 第一部分&#xff1a;创建GUI界面 (使用GUIDE) % 1. 打开GUIDE: guide % 2. 创建新GUI&#xff0c;添加以下控件&#xff1a; % - …

从裸机开发到实时操作系统:FreeRTOS详解与实战指南

从裸机开发到实时操作系统&#xff1a;FreeRTOS详解与实战指南 本文将带你从零开始&#xff0c;深入理解嵌入式系统中的裸机开发与实时操作系统&#xff0c;以FreeRTOS为例&#xff0c;全面剖析其核心概念、工作原理及应用场景。无论你是嵌入式新手还是希望提升技能的开发者&am…

zabbix7.2最新版本 nginx自定义监控(三) 设置触发器

安装zabbix-get服务 在zabbix-server端口安装zabbix-get服务 [rootlocalhost ~]# dnf install -y zabbix-get Last metadata expiration check: 1:55:49 ago on Wed 14 May 2025 09:24:49 AM CST. Dependencies resolved. Package Architectur…

在 Kotlin 中,什么是解构,如何使用?

在 Kotlin 中&#xff0c;解构是一种语法糖&#xff0c;允许将一个对象分解为多个独立的变量。 这种特性可以让代码更简洁、易读&#xff0c;尤其适用于处理数据类、集合&#xff08;如 Pair、Map&#xff09;或其他结构化数据。 1 解构的核心概念 解构通过定义 componentN()…

html的鼠标点击事件有哪些写法

在HTML中&#xff0c;鼠标点击事件的实现方式多样&#xff0c;以下从基础语法到现代实践为您详细梳理&#xff1a; 一、基础写法&#xff1a;直接内联事件属性 在HTML标签内通过on前缀事件属性绑定处理函数&#xff0c;适合简单交互场景&#xff1a; <!-- 单击事件 -->…

基于EFISH-SCB-RK3576/SAIL-RK3576的智能垃圾分类站技术方案

&#xff08;国产化替代J1900的环保物联网解决方案&#xff09; 一、硬件架构设计‌ ‌多模态感知系统‌ ‌高精度识别模块‌&#xff1a; 双光谱成像&#xff08;RGB近红外&#xff09;融合NPU加速ResNet50模型&#xff0c;支持40垃圾品类识别&#xff08;准确率>99.5%&am…

PYTHON训练营DAY27

装饰器 编写一个装饰器 logger&#xff0c;在函数执行前后打印日志信息&#xff08;如函数名、参数、返回值&#xff09; logger def multiply(a, b):return a * bmultiply(2, 3) # 输出: # 开始执行函数 multiply&#xff0c;参数: (2, 3), {} # 函数 multiply 执行完毕&a…

Android Studio 中 build、assemble、assembleDebug 和 assembleRelease 构建 aar 的区别

上一篇&#xff1a;Tasks中没有build选项的解决办法 概述&#xff1a; 在构建 aar 包时通常会在下面的选项中进行构建&#xff0c;但是对于如何构建&#xff0c;选择哪种方式构建我还是处于懵逼状态&#xff0c;所以我整理了一下几种构建方式的区别以及如何选择。 1. build…

视频质量分析时,遇到不同分辨率的对照视频和源视频,分辨率对齐的正确顺序。

背景 我们平时在做视频转码后&#xff0c;会用VMAF/PSNR得评分工具进行视频对比的评分&#xff0c;但是这几种客观评分方式都有一个要求就是分辨率要一模一样&#xff0c;因为这样才对像素点做数学运算。 但是分辨率对齐其实有两种选择&#xff0c;例如源视频是1080P&#xf…

【技巧】离线安装docker镜像的方法

回到目录 【技巧】离线安装docker镜像的方法 0. 为什么需要离线安装&#xff1f; 第一、 由于docker hub被墙&#xff0c;所以 拉取镜像需要配置国内镜像源 第二、有一些特殊行业服务器无法接入互联网&#xff0c;需要手工安装镜像 1. 可以正常拉取镜像服务器操作 服务器…

计算机网络 : 网络基础

计算机网络 &#xff1a; 网络基础 目录 计算机网络 &#xff1a; 网络基础引言1. 网络发展背景2. 初始协议2.1 初始协议2.2 协议分层2.2.1 软件分层的好处2.2.2 OSI七层模型2.2.3 TCP/IP五层&#xff08;四层&#xff09;模型 2.3 TCP/IP协议2.3.1TCP/IP协议与操作系统的关系&…

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…

Jmeter 安装包与界面汉化

Jmeter 安装包&#xff1a; 通过网盘分享的文件&#xff1a;CSDN-apache-jmeter-5.5 链接: https://pan.baidu.com/s/17gK98NxS19oKmkdRhGepBA?pwd1234 提取码: 1234 Jmeter界面汉化&#xff1a;

HandlerInterceptor介绍-笔记

1. HandlerInterceptor简介 org.springframework.web.servlet.HandlerInterceptor 是 Spring MVC 中用于拦截 HTTP 请求的核心接口。 public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object ha…

C++循环效率比较与优化建议

在 C++ 中,不同循环结构(如 for、while、do-while、基于范围的 for)在优化后的性能通常是等效的,因为现代编译器会对它们进行底层优化,生成相似的机器代码。循环的效率更多取决于循环体内的操作和数据访问模式,而非循环结构本身的选择。以下是关键点总结: 1. 传统循环的…

北京孙河傲云源墅:限量典藏的主城墅居臻品

在限墅令的背景下&#xff0c;北京主城的墅居产品日益稀缺&#xff0c;而傲云源墅作为孙河墅区的杰出之作&#xff0c;凭借其独特的价值&#xff0c;成为了众多高端置业者的理想选择。 傲云源墅所处的孙河地区&#xff0c;是北京公认的高价值板块。其地位在 2025 年孙河 2902 …

简单入门RabbitMQ

本章将带大家来写一个简单的程序&#xff0c;使用 Java 创建RabbitMQ 的生产者和消费者 依赖引入 在 Maven 仓库中输入 amqp-client&#xff1a; 找到第一个 RabbitMQ Java Client &#xff0c;点击进去找到一个合适的版本然后将依赖引入到我们项目中的 pom.xml 文件中。 …

Git基础使用方法与命令总结

Git 是一个分布式版本控制系统&#xff0c;用于跟踪代码或文件的修改历史。以下是 Git 的基础使用方法和常用命令&#xff0c;适合快速上手&#xff1a; 1. 安装与配置 安装 Git 下载地址&#xff1a;https://git-scm.com/downloads&#xff08;支持 Windows/macOS/Linux&…

Oracle SYSTEM/UNDO表空间损坏的处理思路

Oracle SYSTEM/UNDO表空间损坏是比较棘手的故障&#xff0c;通常会导致数据库异常宕机进而无法打开数据库。数据库的打开故障处理起来相对比较麻烦&#xff0c;读者可以参考本书第5章进一步了解该类故障的处理过程。如果数据库没有备份&#xff0c;通常需要设置官方不推荐的隐含…