前言
每个新手程序猿都会遇到一些奇奇怪怪的难题,比如说在两个或者多个数据关系表的情况下,需要以一个主表查询出对应关系表的数据,如下关系表说明
准备
数据表说明
- 用户表(user)
- 会员卡表(vip)
- 会员卡附表(vip_fields)
使用场景
- 在很多时候数据列表需要关联多表字段才能满足需求
需求
- 会员卡列表
- 需要有会员昵称/头像/姓名/性别邮箱地址/会员id
实现
- 根据(会员卡)找出会员用户信息已经会员卡附表数据进行关联,以下是两种示例
例1
<?php // 获取会员卡列表 $vips = Vip::find()->offset(0)->limit(10)->asArray()->all(); // 循环组装会员用户信息及会员卡附表数据 foreach($vips as &$row){ // 获取会员卡用户信息 $row['user'] = User::find()->andWhre(['user_id'=>$row['user_id']])->limit(1)->asArray()->one(); // 获取会员卡附表信息 $row['fields'] = VipFIelds::find()->andWhere(['vip_id'=>'vip_id'])->limit(1)->asArray()->one(); } return $vips; ?>
- 运行结果
{
"vip_id": 1,
"user_id": 1,
"user": {
"user_id": 1,
"nickname": "小白",
"avatar": "http://xiaobai.png"
},
"fields": {
"vip_id": 1,
"realname": "小小白",
"sex": 1,
"email": "xiaobai@qq.com"
}
},
{
"vip_id": 2,
"user_id": 2,
"user": {
"user_id": 2,
"nickname": "小米",
"avatar": "http://xiaobai.png"
},
"fields": {
"vip_id": 2,
"realname": "小小米",
"sex": 1,
"email": "xiaomi@qq.com"
}
}
]
例2
<?php // 会员卡列表 $vips = Vip::find()->offset(0)->limit(10)->asArray()->all(); // 用户id $userIds = array_unique(array_column($vips,'user_id')); // 会员卡id $vipIds = array_unique(array_column($vips,'vip_id')); // 会员卡用户信息数据列表 $users = User::find()->andWhere(['user_id'=>$userIds])->asArray()->limit(count($userIds))->all(); // 重组会员卡信息数据 以user_id为key $usersRow = array_column($users,null,'user_id'); // 会员卡附表数据列表 $fields = VipFields::find()->andWhere(['vip_id'=>$vipIds])->asArray()->limit(count($vipIds))->all(); // 重组会员卡附表数据 以 vip_id为key $fieldsRow = array_column($fields,null,'vip_id'); foreach($vips as &$row){ // 组装会员卡用户信息 不存在 为 null $row['user'] = $usersRow[$row['user_id']] ?? null; // 组装会员卡附表信息 不存在 为 null $row['fields'] = $fieldsRow[$row['vip']] ?? null; } return $vips; ?>
- 运行结果
{
"vip_id": 1,
"user_id": 1,
"user": {
"user_id": 1,
"nickname": "小白",
"avatar": "http://xiaobai.png"
},
"fields": {
"vip_id": 1,
"realname": "小小白",
"sex": 1,
"email": "xiaobai@qq.com"
}
},
{
"vip_id": 2,
"user_id": 2,
"user": {
"user_id": 2,
"nickname": "小米",
"avatar": "http://xiaobai.png"
},
"fields": {
"vip_id": 2,
"realname": "小小米",
"sex": 1,
"email": "xiaomi@qq.com"
}
}
]
后言
- 例1 在foreach里面进行数据查询,数据库请求频繁,导致数据库压力较大,数据库请求次数 1+(N*2) 次,对数据库影响较大
- 例2 在查询出会员卡主表后在将关联表关联id单独取出成为数组再进行一批列表查询,重组,数据库请求次数3次
总结
不同的需求都有不同的代码处理逻辑,以例1与例2为示例,虽然例1也能实现接口需求,但是对于数据库影响比较大,不推荐使用,例1虽说处理步骤较多,但是对数据影响较小,可以选择例2使用,如发现更好的方案会继续优化
发表回复