美文网首页
mysql php 如何查询无限层上下级关系树状结构

mysql php 如何查询无限层上下级关系树状结构

作者: 风扬w | 来源:发表于2020-01-18 23:45 被阅读0次

    mysql表结构如下


    user 表结构

    我们先来随机生成数据,以便测试。

    public function createTestData()
    {
        for ($i = 1; $i < 10000; $i++){
            $name = chr(mt_rand(0xB0,0xD0)).chr(mt_rand(0xA1, 0xF0));
            $mark = chr(mt_rand(0xB0,0xD0)).chr(mt_rand(0xA1, 0xF0)).chr(mt_rand(0xB0,0xD0)).chr(mt_rand(0xA1, 0xF0));
            $name = iconv('GB2312', 'UTF-8', $name);
            $mark = iconv('GB2312', 'UTF-8', $mark);
            Db::name("user")->insert([
                'id' => $i,
                'pid' => mt_rand(0, $i-1),
                'name' => $name,
                'mark' => $mark
    
            ]);
    }
    

    那么如何查询出完整的上下关系树状结构图呢?

    1. 笨办法,无限递归查询
        public function getTeamV1()
        {
            // 获取id为5用户的下级数据结构图
            $userInfo = Db::name("user")->where(['id' => 1])->find();
            $userInfo = $this->getChilddrenV1($userInfo);
    
            var_dump($userInfo);
        }
    
        private function getChilddrenV1($userInfo)
        {
            $children = Db::name("user")->where(['pid' => $userInfo['id']])->select();
            if ($children) {
                $userInfo['children'] = $children;
                foreach ($children as $k => $v) {
                    $userInfo['children'][$k] = $this->getChilddrenV1($children[$k]);
                }
            }
            return $userInfo;
        }
    

    该方法耗时程度完全取决于用户数据量,因为每个用户都要单独进行一次sql查询,判断其有没有下级。

    进行的sql语句查询次数 = 下级人数

    这种查询最简单粗暴,但是最不可取,例如上图我查的id为5的用户,还好,结果出来了


    id为5时的结果图

    但是,我如果换成id为1,那么...


    id为1时的结果图

    结果是出来了,但耗时25秒。
    我们一共才1W条随机数据,耗时25秒,这在实际生产环境下,大批量数据的时候是完全不可取的。

    1. sql语句中的in条件查询
    public function getTeamV2()
        {
            // 获取id为5用户的下级数据结构图
            $userInfo = Db::name("user")->where(['id' => 1])->find();
    
            // 先查询第一批childrenId
            $allChildrenId = [];    // 该用户所有的下级id皆放入其中
            $allChildrenInfo = [];    // 该用户所有的下级完整信息皆放入其中
            $_childrenId = [];
            $children = Db::name("user")->where(['pid' => $userInfo['id']])->select();
            if ($children && count($children) > 0) {
                $userInfo['children'] = $children;
    
                foreach ($children as $k => $v) {
                    $allChildrenId[0][] = $v['id'];
                    $allChildrenInfo[$v['id']] = $v;
                    $_childrenId[] = $v['id'];
                }
            }
    
            $hierarchy = 0; // 层级
            do {
                $children = Db::name("user")->whereIn('pid', $_childrenId)->select();
                $hierarchy++;
                if ($children && count($children) > 0) {
                    $_childrenId = [];
                    foreach ($children as $k => $v) {
                        $allChildrenId[$hierarchy][] = $v['id'];
                        $allChildrenInfo[$v['id']] = $v;
                        $_childrenId[] = $v['id'];
                    }
                }
            } while ($children && count($children) > 0);
    
            // 把数据处理成树状结构
            for ($i = 0; $i < $hierarchy-1; $i++) {
                // 对比 $allChildrenId[$i] 与 $allChildrenId[$i+1] 这两层用户的上下级关系
                foreach ($allChildrenId[$i] as $k1 => $v1) {
                    foreach ($allChildrenId[$i + 1] as $k2 => $v2) {
                        if($allChildrenInfo[$v2]['pid'] == $v1){
                            // $v1 是 $v2 的上级
                            
                        }
                    }
                }
            }
    
            var_dump($allChildrenId);
        }
    

    该方法耗时程度取决于层级深度,用户上下级关系的层级越深,则耗时越久。

    进行的sql语句查询次数 = 下级层数

    该方法大大缩短了查询次数,节约了时间,但是需要对数据进行进一步处理以便成为数组结构图

    emmmmm, 明天再写,今天太晚了

    相关文章

      网友评论

          本文标题:mysql php 如何查询无限层上下级关系树状结构

          本文链接:https://www.haomeiwen.com/subject/biblzctx.html