MySQL递归查询笔记

发布于:2024-10-12 ⋅ 阅读:(106) ⋅ 点赞:(0)

目录

一、创建表结构和插入数据

二、查询所有子节点

三、查询所有父节点

四、查询指定节点的根节点

五、查询所有兄弟节点(同级节点)

六、获取祖先节点及其所有子节点

七、查询每个节点之间的层级关系

八、查询指定节点之间的层级关系


一、创建表结构和插入数据

CREATE TABLE `region` (  
    `id` VARCHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '主键',  
    `parent_id` VARCHAR(36) COMMENT '父键',  
    `name` VARCHAR(255) NOT NULL COMMENT '地区名',  
    `latitude` DECIMAL(10, 6) COMMENT '经度',  
    `longitude` DECIMAL(10, 6) COMMENT '纬度',  
    PRIMARY KEY (`id`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (NULL, '江苏省', 31.2304, 120.663);  

SET @jiangsu_id = (SELECT `id` FROM `region` WHERE `name` = '江苏省');  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@jiangsu_id, '苏州市', 31.2988, 120.5853);  

SET @suzhou_id = (SELECT `id` FROM `region` WHERE `name` = '苏州市');  
 
INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@suzhou_id, '张家港市', 31.8754, 120.5553),  
       (@suzhou_id, '吴中区', 31.2622, 120.6446),  
       (@suzhou_id, '相城区', 31.3697, 120.646),  
       (@suzhou_id, '吴江区', 31.1791, 120.6411);  

SET @zhangjiagang_id = (SELECT `id` FROM `region` WHERE `name` = '张家港市');  
SET @wuzhong_id = (SELECT `id` FROM `region` WHERE `name` = '吴中区');  
SET @xiangcheng_id = (SELECT `id` FROM `region` WHERE `name` = '相城区');  
SET @wujiang_id = (SELECT `id` FROM `region` WHERE `name` = '吴江区');  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@zhangjiagang_id, '凤凰镇', 31.8754, 120.5553),  
       (@zhangjiagang_id, '塘桥镇', 31.8754, 120.5553);  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@wuzhong_id, '木渎镇', 31.2622, 120.6446);  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@xiangcheng_id, '黄埭镇', 31.3697, 120.646);  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@wujiang_id, '平望镇', 31.1791, 120.6411),   
       (@wujiang_id, '黎里镇', 31.1791, 120.6411);  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@jiangsu_id, '无锡市', 31.5704, 120.3055);  

SET @wuxi_id = (SELECT `id` FROM `region` WHERE `name` = '无锡市');  

INSERT INTO `region` (`parent_id`, `name`, `latitude`, `longitude`)   
VALUES (@wuxi_id, '锡山区', 31.5887, 120.3573),  
       (@wuxi_id, '惠山区', 31.6514, 120.3036),  
       (@wuxi_id, '滨湖区', 31.5502, 120.2598),  
       (@wuxi_id, '江阴市', 31.9086, 120.2855),  
       (@wuxi_id, '宜兴市', 31.3623, 119.8233);

二、查询所有子节点

从指定的父节点开始,递归查找所有子级地区:

WITH RECURSIVE region_cte AS (  
    SELECT id, name, parent_id  
    FROM region  
    WHERE name = '苏州市'  -- 根据指定父节点开始  

    UNION ALL  

    SELECT r.id, r.name, r.parent_id  
    FROM region r  
    JOIN region_cte c ON r.parent_id = c.id  -- 递归查找所有子地区  
)  
SELECT * FROM region_cte

查询结果:

三、查询所有父节点

从指定的子节点开始,递归查找所有父级地区:

WITH RECURSIVE region_cte AS (  
    SELECT id, name, parent_id  
    FROM region  
    WHERE name = '张家港市'  -- 从指定子节点开始  

    UNION ALL  

    SELECT r.id, r.name, r.parent_id  
    FROM region r  
    JOIN region_cte c ON r.id = c.parent_id  -- 递归查找父级区域  
)  
SELECT * FROM region_cte

查询结果:

四、查询指定节点的根节点

可以通过递归查找父节点,最终筛选出根节点(即没有父节点的):

WITH RECURSIVE region_cte AS (  
    SELECT id, name, parent_id  
    FROM region  
    WHERE name = '张家港市'  -- 从指定节点开始  

    UNION ALL  

    SELECT r.id, r.name, r.parent_id  
    FROM region r  
    JOIN region_cte c ON r.id = c.parent_id  -- 递归查找父级区域  
)  
SELECT * FROM region_cte  
WHERE parent_id IS NULL  -- 筛选根节点

查询结果:

五、查询所有兄弟节点(同级节点)

查找与指定节点同级的所有区域:

SELECT id, name, parent_id  
FROM region  
WHERE parent_id = (SELECT parent_id FROM region WHERE name = '张家港市')  -- 获取同级父节点  
AND name != '张家港市'  -- 排除自身

查询结果:

六、获取祖先节点及其所有子节点

获取指定节点的祖先以及每个祖先的所有子节点:

WITH RECURSIVE region_ancestors AS (  
    SELECT id, name, parent_id  
    FROM region  
    WHERE name = '张家港市'  -- 从指定节点开始查找祖先  

    UNION ALL  

    SELECT r.id, r.name, r.parent_id  
    FROM region r  
    JOIN region_ancestors c ON r.id = c.parent_id  -- 递归查找所有父级区域  
),  
region_children AS (  
    SELECT id, name, parent_id  
    FROM region  

    UNION ALL  

    SELECT r.id, r.name, r.parent_id  
    FROM region r  
    JOIN region_children c ON r.parent_id = c.id  -- 递归查找所有子级区域  
)  
SELECT * FROM region_ancestors  
UNION  
SELECT * FROM region_children  
WHERE parent_id IN (SELECT id FROM region_ancestors)  -- 获取所有祖先的子节点

查询结果:

七、查询每个节点之间的层级关系

返回每个地区的详细信息,包括其层级和路径:

WITH RECURSIVE region_tree (id, name, parent_id, level, path) AS (  
    -- 选择根节点,即没有父节点的区域  
    SELECT  
        id,  
        name,  
        parent_id,  
        1 AS level,  
        CAST(name AS CHAR(200)) AS path  
    FROM region  
    WHERE parent_id IS NULL  

    UNION ALL  

    -- 递归查找子区域  
    SELECT  
        r.id,  
        r.name,  
        r.parent_id,  
        rt.level + 1 AS level,  
        CONCAT(rt.path, ' -> ', r.name) AS path  
    FROM region r  
    JOIN region_tree rt ON r.parent_id = rt.id  
)  
-- 查询结果  
SELECT  
    id, name, parent_id, level, path  
FROM region_tree  
ORDER BY id  -- 根据需要排序

查询结果:

八、查询指定节点之间的层级关系

假设获取苏州市(或其他特定节点)的所有子节点及其层级结构

WITH RECURSIVE region_tree (id, name, parent_id, level, path) AS (  
    -- 选择指定节点作为根节点  
    SELECT  
        id,  
        name,  
        parent_id,  
        1 AS level,  
        CAST(name AS CHAR(200)) AS path  
    FROM region  
    WHERE name = '苏州市'  -- 替换为你想要查询的节点名称  

    UNION ALL  

    -- 递归查找子区域  
    SELECT  
        r.id,  
        r.name,  
        r.parent_id,  
        rt.level + 1 AS level,  
        CONCAT(rt.path, ' -> ', r.name) AS path  
    FROM region r  
    JOIN region_tree rt ON r.parent_id = rt.id  
)  
-- 查询结果  
SELECT  
    id, name, parent_id, level, path  
FROM region_tree  
ORDER BY level, id  -- 根据层级和 ID 排序

查询结果:


网站公告

今日签到

点亮在社区的每一天
去签到