php 循环里面套sql怎么解决

时间:2022-02-13 06:21:59
功能要求: 企业列表(展示企业的基本信息,这里只获取了名称、logo、和服务类型), 服务类型说明: 服务类型一共3级,1、2级是必填的,3级是非必填,如果填的话最多3个,  服务类型1、2、3保存在一张表, pid作为关联字段(默认为0)

企业列表数据结构   服务类型1、2级都是唯一的所有查询企业数据时就关联获取到了
 array:4 [
0 => array:6 [
"id" => 1
"company_name" => "公司名称1"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 101
"name" => "金融服务"
]
"service_type2" => array:2 [
"id" => 102
"name" => "理财"
]
"service_type3" => "826,827,828"
]
1 => array:6 [
"id" => 2
"company_name" => "公司名称2"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => 0
"service_type2" => 0
"service_type3" => 0
]
2 => array:6 [
"id" => 3
"company_name" => "公司名称3"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 13
"name" => "日用百货"
]
"service_type2" => array:2 [
"id" => 15
"name" => "文具"
]
"service_type3" => "291,292,295"
]
3 => array:6 [
"id" => 4
"company_name" => "公司名称4"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 48
"name" => "信息服务"
]
"service_type2" => array:2 [
"id" => 50
"name" => "操作系统"
]
"service_type3" => "523,524,526"
]
]

问题就是第三级是用逗号隔开保留的数据,关联查不好查,所以需要单独的处理第三级的数据,怎么弄?

 //我这里用的是laravel框架,数据库的交互都是封装好的  下面是根据封装的方法处理的查询数据
foreach( $data as $key => &$vo ){
//首先将第三级的数据整理成一个一维数组
$service_type3 = explode( ',' , $vo['service_type3'] );
$arr_option3['whereIn'] = ['id' => $service_type3]; //whereIn查询指定的数据
$arr_option3['field'] = ['id','name']; //只获取指定的字段信息
$vo['service_type3'] = CompanyServiceTypeRepository::getAll( $arr_option3 ); //查询数据
}

这是执行上面代码数据的结果

 array:4 [
0 => array:6 [
"id" => 1
"company_name" => "公司名称1"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 101
"name" => "金融服务"
]
"service_type2" => array:2 [
"id" => 102
"name" => "理财"
]
"service_type3" => array:3 [
0 => "外汇"
1 => "基金"
2 => "股票"
]
]
1 => array:6 [
"id" => 2
"company_name" => "公司名称2"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => 0
"service_type2" => 0
"service_type3" => []
]
2 => array:6 [
"id" => 3
"company_name" => "公司名称3"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 13
"name" => "日用百货"
]
"service_type2" => array:2 [
"id" => 15
"name" => "文具"
]
"service_type3" => array:3 [
0 => "桌面用品"
1 => "办公本薄"
2 => "文件装整"
]
]
3 => & array:6 [
"id" => 4
"company_name" => "公司名称4"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 48
"name" => "信息服务"
]
"service_type2" => array:2 [
"id" => 50
"name" => "操作系统"
]
"service_type3" => array:3 [
0 => "虚拟机系统"
1 => "Unix/Linux"
2 => "Windows/dos"
]
]
]

数据结果正确?  是的正确的  也是我想要的数据机构。  但是当时没有考虑明白,  现在只有4条数据,那么就要循环4次去获取第三级分类名称,要是数据是10条?20条? all?  那不就给数据库增加压力了吗,而且如果有好几家公司的第三级数据相同的话,是不是重复执行了相同的sql语句? 这一层面上是不是又造成了资源浪费。

所有称同事没有注意到我个代码 , 立马 马不停蹄的赶紧改掉,怎么改?   先提供一个思路吧在贴代码

我们一点要避免循环里面套sql查询, 这个你会有意想不到的结果。所有我的思路是将所有企业的第三级数据整理成一个数组,统一去查出所有的第三级名称,在循环数组将对应的名称保存到对应的企业下保存起来。

下面我来贴出代码,虽然代码量会比上面foreach查询的量多一些,但是效率和资源浪费上面提升了很多。

使用到的相关php函数,基本上都是常用函数(具体函数说明请自行百度): array_column() 、implode()、explode()、array_values()、asort()、array_unique()、array_shift()

 $service_type3 = array_column( $data , 'service_type3');  //这里会得到一个一维数组,元素是上面$data数据的service_type3字段数据
$service_type3 = implode( ',' , $service_type3 ); //将数据切割成字符串 得到的结果是 "826,827,828,0,291,292,295,523,524,526"
$service_type3 = explode(',', $service_type3 ); //再次将上面的字符串切割成数组(很有必要) 得到的又是一个一维数组,和第一步的数据是不一样的
$service_type3 = array_unique( $service_type3 ); //数组去重
//第一种方法 尽可能的使用php定义的函数
asort( $service_type3 ); //将数组内的元素由低到高进行一下排序(也很有必要,因为又可以会有0在里面,由于上面去重了一次,所有经过排序后如果有0元素的话会在第一位)
$service_type3 = array_values( $service_type3 ); //重新定义数组的索引
if( $service_type3[0] == 0 ){ //如果数组的第一个元素是0
array_shift( $service_type3 ); //删除第一个元素
}
//第二种方法
// foreach ( $service_type3 as $key => $vo ){
// if( $vo == 0 ){
// unset( $service_type3[$key] );
// }
// }

最终得到的数据

 array:8 [
0 => "826"
1 => "827"
2 => "828"
4 => "291"
5 => "292"
6 => "295"
7 => "523"
8 => "524"
]

接下来我们在查询第三级的类型名称   这里就只用查询一次数据库就能查出所有的第三级类型名称数据了

 $arr_option3['whereIn'] = ['id' => $service_type3];     //所有3级的id
$arr_option3['field'] = ['id','name'];
$arr_service_type3 = CompanyServiceTypeRepository::getAll( $arr_option3 ); //获取第三级服务类型名称
$arr_service_type3 = array_column( $arr_service_type3 ,'name' ,'id'); //将数据整理成id为键 name为值的一维键值对数组

得打的结果

 array:8 [
828 => "外汇"
827 => "基金"
826 => "股票"
524 => "Unix/Linux"
523 => "Windows/dos"
295 => "桌面用品"
292 => "办公本薄"
291 => "文件装整"
]

最后将数据保存到对应的企业列表中, 可以对比一下与上面循环里面套sql得到的结果是否一样

 foreach ( $data as $key => &$vo ){
if( $vo['service_type3'] != 0 ){
$service_type3 = explode( ',' , $vo['service_type3']); //将字符串切割成数组
$vo['service_type3'] = [];
foreach ( $service_type3 as $k => $v ){
$vo['service_type3'][] = $arr_service_type3[$v];
}
}else{
$vo['service_type3'] = [];
}
11 }

最终得到的结果

 array:4 [
0 => array:6 [
"id" => 1
"company_name" => "公司名称1"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 101
"name" => "金融服务"
]
"service_type2" => array:2 [
"id" => 102
"name" => "理财"
]
"service_type3" => array:3 [
0 => "股票"
1 => "基金"
2 => "外汇"
]
]
1 => array:6 [
"id" => 2
"company_name" => "公司名称2"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => 0
"service_type2" => 0
"service_type3" => []
]
2 => array:6 [
"id" => 3
"company_name" => "公司名称3"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 13
"name" => "日用百货"
]
"service_type2" => array:2 [
"id" => 15
"name" => "文具"
]
"service_type3" => array:3 [
0 => "文件装整"
1 => "办公本薄"
2 => "桌面用品"
]
]
3 => & array:6 [
"id" => 4
"company_name" => "公司名称4"
"logo" => "men_hu/picture/2020-07/5f07e6df5561f.jpg"
"service_type1" => array:2 [
"id" => 48
"name" => "信息服务"
]
"service_type2" => array:2 [
"id" => 50
"name" => "操作系统"
]
"service_type3" => array:3 [
0 => "Windows/dos"
1 => "Unix/Linux"
2 => "Unix/Linux"
]
]
]

还是那句话  尽量不要在循环里面套sql语句, 我这里应该第三级的数据不是固定的可以无限的添加,所以才整理成数组用whereIn查询了一次, 但是如果服务类型个数有限(100个以内的话), 直接全部多出来,在出来数组(这里我就不仔细说了 懂的自然懂)

说白了就是php处理数组、数据的能了肯定比你查询数据库厉害