如何用PHP递归遍历MySQL二叉树表并统计指定根节点下各Rank人数
递归遍历二叉树统计指定根节点下各Rank人数(PHP+MySQL实现)
假设的MySQL表结构
先假设你的二叉树表结构如下(请根据实际表结构调整字段名):
CREATE TABLE tree_nodes ( id INT PRIMARY KEY AUTO_INCREMENT, parent_id INT COMMENT '父节点ID,根节点可设为0或NULL', name VARCHAR(50) NOT NULL COMMENT '节点名称', rank INT COMMENT '用户等级', FOREIGN KEY (parent_id) REFERENCES tree_nodes(id) );
PHP实现代码
使用MySQL递归CTE(Common Table Expression)高效查询所有子节点,再通过PHP补全指定Rank的统计结果:
<?php // 数据库连接参数 $dbConfig = [ 'host' => 'localhost', 'dbname' => 'your_db_name', 'username' => 'your_username', 'password' => 'your_password' ]; try { // 初始化PDO连接 $pdo = new PDO( "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset=utf8mb4", $dbConfig['username'], $dbConfig['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] ); // 目标根节点ID $rootId = 2; // 获取根节点名称 $getNameStmt = $pdo->prepare("SELECT name FROM tree_nodes WHERE id = ?"); $getNameStmt->execute([$rootId]); $rootName = $getNameStmt->fetchColumn(); if (!$rootName) { echo "指定的根节点不存在"; exit; } // 递归查询根节点下所有子节点的Rank数据 $recursiveSql = " WITH RECURSIVE node_hierarchy AS ( -- 初始查询:根节点的直接子节点 SELECT id, rank FROM tree_nodes WHERE parent_id = ? UNION ALL -- 递归查询:所有后代节点 SELECT tn.id, tn.rank FROM tree_nodes tn JOIN node_hierarchy nh ON tn.parent_id = nh.id ) SELECT rank, COUNT(*) AS user_count FROM node_hierarchy WHERE rank IS NOT NULL -- 过滤无等级的节点 GROUP BY rank ORDER BY rank; "; $statsStmt = $pdo->prepare($recursiveSql); $statsStmt->execute([$rootId]); // 转换为Rank为键、人数为值的数组 $rankStats = $statsStmt->fetchAll(PDO::FETCH_KEY_PAIR); // 补全Rank 1-4的统计(无数据则设为0) $targetRanks = [1, 2, 3, 4]; $finalStats = []; foreach ($targetRanks as $rank) { $finalStats[$rank] = $rankStats[$rank] ?? 0; } // 输出结果 echo "Root > {$rootName}\n"; foreach ($finalStats as $rank => $count) { echo "Rank {$rank}用户数:{$count}\n"; } } catch (PDOException $e) { die("数据库操作失败:" . $e->getMessage()); } ?>
代码说明
- 递归CTE查询:通过
WITH RECURSIVE语法一次性获取根节点下所有后代节点,比PHP递归查询数据库效率更高。 - 结果补全:确保Rank 1到4的统计都存在,即使某个Rank没有用户也显示0。
- 灵活调整:如果需要包含根节点自身的统计,只需将CTE的初始查询改为
SELECT id, rank FROM tree_nodes WHERE id = ?。
内容的提问来源于stack exchange,提问作者Mudassar Akram
相关产品推荐
相关产品推荐

