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
]);
}
那么如何查询出完整的上下关系树状结构图呢?
- 笨办法,无限递归查询
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秒,这在实际生产环境下,大批量数据的时候是完全不可取的。
- 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, 明天再写,今天太晚了
网友评论