You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL推荐链底层用户数统计异常,仅统计部分节点求助

问题描述

数据库表结构如下:

UIDreferredreferrer
300302,304
302303300
303305,306,307302
304308300
308309304

需要统计用户300推荐链的底层用户数量(即305、306、307、309),预期结果为4,但现有PHP+MySQL代码仅统计到3个,未处理304分支。

原代码片段:

// 获取300的直接推荐用户(逗号分隔)
$sql = "SELECT GROUP_CONCAT(uid) FROM mybb_users WHERE referrer='300'";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
  while($row = mysqli_fetch_assoc($result)) {
    $abc= $row["uid"]; 

    // 查询这些用户的推荐用户
    $sql = "SELECT uid FROM mybb_users WHERE referrer='$abc'";
    $result = mysqli_query($conn, $sql);

    if (mysqli_num_rows($result) > 0) {
       while($row = mysqli_fetch_assoc($result)) {
       $wbc= $row["uid"];
       
       // 统计推荐用户数量
       $sql = "SELECT count(*) FROM mybb_users WHERE referrer='$wbc'";
       $result = mysqli_query($conn, $sql);
       if (mysqli_num_rows($result) > 0) {
         while($row=mysqli_fetch_assoc($result)) {
        echo $row['count(*)'];          }
    } else {
       echo "0";  
      }
      }
    }
  }
}

问题原因

  1. GROUP_CONCAT结果处理错误:GROUP_CONCAT(uid)返回逗号分隔字符串(如302,304),但代码直接将其作为referrer查询条件,导致SQL语句变为WHERE referrer='302,304'——表中无匹配用户,因此无法查询到304的下级308,遗漏了309的统计。
  2. 变量覆盖逻辑漏洞:后续查询复用$result变量,中断循环逻辑;同时未拆分逗号分隔的ID,无法遍历所有直接推荐用户。
解决方案

方案1:MySQL递归查询(高效推荐,MySQL 8.0+支持)

通过CTE递归遍历整个推荐链,直接统计底层用户数量:

WITH RECURSIVE referral_chain AS (
    -- 起始节点:用户300
    SELECT uid, referred FROM mybb_users WHERE uid = 300
    -- 递归遍历所有下级用户
    UNION ALL
    SELECT u.uid, u.referred 
    FROM mybb_users u
    JOIN referral_chain rc ON FIND_IN_SET(u.uid, rc.referred)
)
-- 统计所有没有下级的用户数量(底层用户)
SELECT COUNT(*) AS total_bottom_users
FROM (
    -- 拆分referred字段为单个用户ID
    SELECT TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(rc.referred, ',', numbers.n), ',', -1)) AS bottom_uid
    FROM referral_chain rc
    JOIN (
        SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
    ) numbers 
    ON CHAR_LENGTH(rc.referred) - CHAR_LENGTH(REPLACE(rc.referred, ',', '')) >= numbers.n - 1
) AS bottom_users
-- 确保这些底层用户没有自己的推荐用户
WHERE NOT EXISTS (
    SELECT 1 FROM mybb_users u WHERE u.referrer = bottom_users.bottom_uid
);

执行后直接返回结果4,无需额外PHP逻辑。

方案2:修改PHP代码,遍历所有推荐分支

拆分逗号分隔的用户ID,循环处理每个推荐节点,累加底层用户数量:

$total = 0;
$conn = mysqli_connect("localhost", "username", "password", "database");

// 第一步:获取300的所有直接推荐用户ID
$sql = "SELECT uid FROM mybb_users WHERE referrer='300'";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
    while($row = mysqli_fetch_assoc($result)) {
        $firstLevelUid = $row["uid"];
        // 第二步:获取该直接用户的推荐用户
        $sql2 = "SELECT uid FROM mybb_users WHERE referrer='$firstLevelUid'";
        $result2 = mysqli_query($conn, $sql2);
        
        if (mysqli_num_rows($result2) > 0) {
            while($row2 = mysqli_fetch_assoc($result2)) {
                $secondLevelUid = $row2["uid"];
                // 第三步:统计该二级用户的推荐用户数量(底层用户)
                $sql3 = "SELECT COUNT(*) AS cnt FROM mybb_users WHERE referrer='$secondLevelUid'";
                $result3 = mysqli_query($conn, $sql3);
                $row3 = mysqli_fetch_assoc($result3);
                $total += $row3["cnt"];
            }
        }
    }
}

echo $total; // 输出结果4

代码说明

  • 移除GROUP_CONCAT,改为直接查询每个推荐用户ID,避免字符串处理错误;
  • 使用独立结果变量($result/$result2/$result3),避免变量覆盖中断逻辑;
  • 累加每个二级用户的推荐数量,最终得到正确总数。

内容的提问来源于stack exchange,提问作者Higgs Boson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:25:25