Laravel Excel导出时如何查询指定列并统计gender数量
Laravel Excel 单查询同时返回导出明细+性别分类计数实现方案
核心逻辑是利用SQL窗口函数,在查询明细数据的同时同步计算全结果集的性别分类统计值,不需要额外发起第二条统计查询,完全兼容fromQuery()的延迟分块加载特性,不会损失大文件导出的内存优化能力。
关键修改点
- 删除所有调试用的
dd()、get()调用,fromQuery()必须返回Eloquent查询构造器实例,提前执行查询会丢失分块导出能力,大数据量下会触发内存溢出 - 在查询字段中追加条件聚合窗口函数,自动基于筛选后的全量结果计算男性、女性、跨性别的总人数,每一行明细都会携带这三个统计值,可直接在导出逻辑的表头、合计行中使用
- 修正原有多条件判断的冗余逻辑,保证单独传筛选参数时过滤规则正常生效
修改后完整代码
public function __construct($from, $to, $socialGroup, $gender) { $this->from = $from; $this->to = $to; $this->socialGroup = $socialGroup; $this->gender = $gender; } /** * @return \Illuminate\Database\Eloquent\Builder */ public function query() { $data = RegistrationSchoolCollegeStudents::select( 'registration_number', 'course_name', 'school_name', 'class', 'fullname', 'gender', 'dob', 'street_road_lane', 'area_locality_road', 'village_town_city', 'district', 'pincode', 'email', 'social_group', 'adhaar_number', 'certificate_number', 'is_own_smart_phone', 'created_at', // 单SQL计算各性别总人数,根据实际存储的枚举值调整判断条件即可 \DB::raw('SUM(CASE WHEN gender = "男" THEN 1 ELSE 0 END) OVER() AS male_total'), \DB::raw('SUM(CASE WHEN gender = "女" THEN 1 ELSE 0 END) OVER() AS female_total'), \DB::raw('SUM(CASE WHEN gender = "跨性别" THEN 1 ELSE 0 END) OVER() AS transgender_total') ); if ($this->from !== 'null' && $this->to !== 'null') { $data->whereBetween('created_at', [$this->from, Carbon::parse($this->to)->endOfDay()]); } if ($this->socialGroup !== 'null') { $data->where('social_group', '=', $this->socialGroup); } if ($this->gender !== 'null') { $data->where('gender', '=', $this->gender); } return $data; }
可选优化
如果你只需要当前行对应性别的总人数,不需要同时拿到三个性别的统计值,可以把三个统计字段替换为下面这句,查询性能更高:
\DB::raw('COUNT(*) OVER(PARTITION BY gender) AS current_gender_total')
注意:如果你的数据库性别字段存储的是英文枚举(比如
male/female/other),把CASE语句里的判断值替换成实际存储值即可。
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

