CodeIgniter中基于JSON格式组ID统计各邮件组成员数量的实现问题
解决邮件组成员统计问题
嘿,我来帮你搞定这个统计邮件组成员的问题!首先咱们先看看你现有代码为啥没输出,然后再给你几种靠谱的解决方案。
你的代码为啥没输出?
仔细看了下你的代码,问题主要出在这几点:
- 变量未定义:
$group->mailGroupId这个变量在循环里根本没定义,你没告诉程序要统计哪个组的成员,所以in_array的条件永远不成立,自然不会进入后续逻辑。 - 逻辑冗余且错误:你已经从
person表拿到了所有用户数据,却又在循环里重新查询单个用户的行数——这完全没必要,而且你统计的是单个用户的存在性(结果要么是1要么是0),不是某个组的总人数。 - 未处理JSON解码异常:如果
personEmailGroup字段不是合法的JSON格式,json_decode会返回null,这时候in_array会直接报错,导致程序中断。
解决方案:高效统计组内成员
方案1:用数据库JSON函数直接统计(推荐)
如果你的数据库是MySQL 5.7+或者支持JSON操作的数据库,可以直接用JSON_CONTAINS函数让数据库帮你完成统计,这样效率最高,不用把所有用户数据拉到PHP里处理。
用CodeIgniter的话,代码可以这么写:
// 先获取所有邮件组 $allGroups = $this->db->get("groups")->result(); foreach ($allGroups as $group) { // 统计当前组的活跃成员数:使用JSON_CONTAINS匹配组ID,同时筛选状态为1的用户 $memberCount = $this->db->where('personStatus', 1) ->where("JSON_CONTAINS(personEmailGroup, '{$group->mailGroupId}')") ->count_all_results('person'); // 输出结果 echo "{$group->mailGroupName} 有 {$memberCount} 人<br>"; }
方案2:PHP层面处理(兼容旧数据库)
如果你的数据库不支持JSON函数,可以先把所有活跃用户拉到PHP里,再遍历统计每个组的成员数:
// 先获取所有状态为1的活跃用户 $activePersons = $this->db->where('personStatus', 1)->get("person")->result(); // 初始化数组存储每个组的成员计数 $groupMemberCounts = []; foreach ($activePersons as $person) { // 解码用户所属的组ID数组,第二个参数传true转成关联数组,同时处理解码失败的情况 $userGroupIds = json_decode($person->personEmailGroup, true); // 如果解码失败或者不是数组,直接跳过这个用户 if (!is_array($userGroupIds)) { continue; } // 遍历用户所属的每个组,累加计数 foreach ($userGroupIds as $groupId) { if (!isset($groupMemberCounts[$groupId])) { $groupMemberCounts[$groupId] = 0; } $groupMemberCounts[$groupId]++; } } // 最后把组ID和组名对应起来,输出统计结果 $allGroups = $this->db->get("groups")->result(); foreach ($allGroups as $group) { $count = isset($groupMemberCounts[$group->mailGroupId]) ? $groupMemberCounts[$group->mailGroupId] : 0; echo "{$group->mailGroupName} 有 {$count} 人<br>"; }
长远优化建议:换用中间表存储多对多关系
其实用JSON存储用户和组的多对多关系,后续查询、统计都会很麻烦,性能也不好。更规范的做法是建一个中间表person_group,专门存储用户和组的关联关系:
CREATE TABLE person_group ( personId INT NOT NULL, mailGroupId INT NOT NULL, PRIMARY KEY (personId, mailGroupId), FOREIGN KEY (personId) REFERENCES person(personId), FOREIGN KEY (mailGroupId) REFERENCES groups(mailGroupId) );
之后统计成员数就简单多了,直接用GROUP BY就能搞定:
$groupStats = $this->db->select('g.mailGroupName, COUNT(pg.personId) AS memberCount') ->from('groups g') ->join('person_group pg', 'g.mailGroupId = pg.mailGroupId', 'left') ->join('person p', 'pg.personId = p.personId AND p.personStatus = 1', 'left') ->group_by('g.mailGroupId, g.mailGroupName') ->get()->result(); // 输出结果 foreach ($groupStats as $stat) { echo "{$stat->mailGroupName} 有 {$stat->memberCount} 人<br>"; }
这种方式不仅统计效率高,后续修改用户所属组、查询用户的组列表也都会更方便,是多对多关系的标准存储方案。
内容的提问来源于stack exchange,提问作者Damien Falborgson
相关产品推荐
相关产品推荐

