PHP优化循环嵌套问题之array_column和collect集合分组

本文探讨了PHP中处理大量推广数据时,如何通过array_column和collect函数减少数据库查询次数,优化循环嵌套,以提高统计推广人用户行为(如访问数、购买量和转化率)的效率。关键技巧包括集合分组、数组操作和数据过滤,以降低复杂度并避免数据冗余。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PHP优化循环嵌套问题之array_column和collect集合分组

  • 场景:统计推广渠道引入用户数量和带来收益[推广渠道数量少,推广用户数量多]
  • 需求:统计推广人、访客数、购买人数、营业额、转化率
  1. 推广日志表:channel_log (推广人/userId)
  2. 订单表:order(userId/支付金额)
思路1
a.通过推广日志表,统计推广人带来用户
	select 推广用户, GROUP_CONCAT(distinct userId) AS 全部用户Id,count(distinct user_id) AS 用户数 from channel_log group by 推广用户
	[
		[
			'推广人' => 'a',
			'全部用户Id' => '1,2,3',
			'用户数' => 3
		],
		....
	]

b.通过订单表,whereIn统计推广人带来收益统计
	for(推广列表) {
		通过 where In 用户Id 统计营业额和购买人数
	}

不足:
1、GROUP_CONCAT有长度限制,默认1024个字节,过长会被截取
2、频繁请求数据库,影响效率

优化:减少频繁请求数据库

思路2
a.通过推广日志表获得基础数据
	select 推广人, userId from channel_log group by 推广用户,userId
	[
		[
			'推广人' => 'a',
			'用户Id' => '1',
		],
		[
			'推广人' => 'b',
			'用户Id' => '2',
		],
		....
	]

b.通过订单表,统计全部用户分别消费金额
	select 用户ID,消费金额 whereIn 所有用户ID group by 用户ID

c.通过遍历,计算推广人带来收益统计

不足:
1、多层遍历,复杂度比较高,数量过大容易内存溢出
2、whereIn的数量不能过多

优化:减少复杂度

思路3:
1、通过推广日志表获得基础数据(思路2第一步)
2、获取$list后,集合分组
	<!-- 集合分组并且排序(对象) -->
	$list = collect($list)->groupBy("key")->sortBy(function ($item) {
	    return count($item);
	});

	[
		{
			key: "a",
			userId: "1"
		},
		{
			key: "b",
			userId: "2"
		}
	]

	转成
	{
		a: [
			{
				key: "a",
				userId: "1"
			}
		],
		b: [
			{
				key: "b",
				userId: "2"
			}
		]
	}

	最后可以转成
	[
		[
			'key' => a,
			'userIds' => [1]
		],
		[
			'key' => b,
			'userIds' => [2]
		]
	]
3、通过订单表,统计全部用户分别消费金额(不要whereIn,会造成多余无关用户,后面有剔除)
4、订单统计分组,统计用户消费金额,以用户ID为KEY(为了后续查询)
	<!-- 分组(数组) -->
	$orderList = array_column($orderList, null, 'userId'); // key值为userId
	[
		['userId' => 2, 'amount' => 3],
		['userId' => 3, 'amount' => 3]
	]
	转成
	[
		'2' => [
			['userId' => 2, 'amount' => 3],
		],
		'3' => [
			['userId' => 3, 'amount' => 3]
		]
	]
5、所有用户/支付用户
	//所有用户
	$allUserIds = array_unique(array_flatten(array_pluck($list, 'userIds')));
	// 支付用户:剔除非来源用户,全部为支付订单 
	$orderUserIds = array_intersect($allUserIds, $orderUserIds); 
6、统计数据
	foreach(推广列表 as $item) {
		$userIds = $item['userIds']// 邀请用户列表
		$payUserIds = array_intersect($userIds, $orderUserIds);// 支付用户,减少数据
		for($payUserIds as $userId) {
			$orderList[$userId] // 复杂度为1
		}
	}
  • 总结:
  • 1、尽量减少复杂度,O(1)替代O(N^2)
  • 2、减少数据量,用array_intersect
  • 3、用户集合分组(collect)和array_column将数组数量减少,降低时间复杂度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值