如果我需要查询出1万以上的记录,又要关联其他表的字段,怎么做效率会快?

$cardNoBegin = 1;
$cardNoEnd = 10000;
$where['number'] = array('between' , [$cardNoBegin , $cardNoEnd]);
$list = VipCardModel::where($where)->field('id,number,issue_uid,rank')->select();
foreach($list as &$value){
    // 只想到foreach来处理,但是这样很奇怪,觉得这样处理不对。
    $value['name'] = UserModel::where(array('id' => $value['issue_uid']))->value('name');
}
阅读 3.7k
7 个回答

shmiyle同学已经正确的回答了这个问题,我在他的基础上优化一下,提升一点效率

$where['number'] = array('between' , [$cardNoBegin , $cardNoEnd]);
$list = VipCardModel::where($where)->field('id,number,issue_uid,rank')->select();
$issueUidList = array_unique((array_column($list, 'issue_uid')));
unset($list);

//查询用户信息
$userList = UserModel::where(array('id' => array('in', $issueUidList)))->value('name');
$userInfoList=array_column($userList,'name','id');

foreach($list as $key => $value){
    $list[$key]['name'] = $userInfoList[$value['issue_uid']] ?? '';
}

这样肯定是不可取的,循环里面执行查询。
可以试试with

$list = VipCardModel::where($where)->with('user')->field('id,number,issue_uid,rank')->select();
$where['number'] = array('between' , [$cardNoBegin , $cardNoEnd]);
$list = VipCardModel::where($where)->field('id,number,issue_uid,rank')->select();
$issueUidList = array_values(array_column($list, 'issue_uid'));

//查询用户信息
$userList = UserModel::where(array('id' => array('in', $issueUidList)))->value('name');

$userInfoList = [];
foreach ($userList as $item) {
    $userInfoList[$item['id']] = $item['name'];
}

foreach($list as $key => $value){
    $list[$key]['name'] = $userInfoList[$value['issue_uid']];
}

//list的信息里带了 name 数据, 当然此处你可以直接用join进行联合查询

我提供两个个思路
第一个:

1.先根据条件查询出主表的记录,以主键id作为key(方便后面塞关联数据),
2.再取出关联字段,根据关联字段,获取关联表相关数据(这里建议关联表的关联字段做索引,加快检索效率),
3.将关联数据使用foreach或者array_walk塞回返回的主表数据。(数据量多的话建议用array_walk,速度比foreach快)

第二个:

主表关联从表一起查询,这样一步到位,不需要再查询,或者再塞数据,但是效率可能没有第一个快。

如果是分页建议使用第一张表差出来id
第二个表做 in 操作
如果是超过1万的数据,建议直接使用dump等离线工具,结合实际的需求考虑,因为本身in数量大了以后性能很不好

宗旨:
1、不要在循环里边执行Sql
2、尽量不要使用联合查询
以上两点都会给mysql带来很大的负担,正确的做法应该是将计算和关联的工作交给php去处理
思路:
1、用最精简的sql拿到所需数据
2、通过php的循环来关联这些数据

这样肯定是不可取的,循环里面执行查询。
可以试试with

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题