withCount的使用
基础概念
统计关联数量,只能使用与Eloquent模型,不用使用DB::table这种查询,使用时候要存在明确的关联Model
没有withSum、withAvg这样的用法,可以通过withCount实现多种聚合查询,适用于一对多的查询
数据表
班级表(student_class)
- id
- name
学生表(student)
- id
- name
- age
- student_id
代码分析
// Model:StudentClass
public function Student(){
return $this->hasMany(Student::class) ;
}
//1.查询所有班级以及每个班级的人数数量,默认形式count(id)
$result1=StudentClass::withCount('student')->get();
// 执行结果:
$result2=[
0 => [
"id" => 1
"name" => "一年级"
"student_count" => 2
]
1 => [
"id" => 2
"name" => "二年级"
"student_count" => 1
]
];
//2.查询所有班级以及每个班级的所有人数以及平均年龄
$result = StudentClass::withCount([
'student as avg_age' => function ($query) {
$query->select(DB::raw('avg(age)'));
},
'student as sum_id' => function ($query) {
$query->select(DB::raw('sum(id)'));
},
])
//进行having筛选,直接使用as字段名称
->having('sum_id','>',6)
//进行排序,直接使用as的字段名称
->orderBy('avg_age','Asc')
->get()
// 执行结果:
$result2=[
0 => [
"id" => 1
"name" => "一年级"
"avg_age" => "15.0000"
"sum_id" => "3"
]
1 => [
"id" => 2
"name" => "二年级"
"avg_age" => "10.0000"
"sum_id" => "3"
]
];
执行sql
-- $result1
select
`student_class`.*,
(
select
count(*)
from
`student`
where
`student_class`.`id` = `student`.`class_id`
) as `student_count`
from
`student_class`
-- result2
select
`student_class`.*,
(
select
avg(age)
from
`student`
where
`student_class`.`id` = `student`.`class_id`
) as `avg_age`,
(
select
sum(id)
from
`student`
where
`student_class`.`id` = `student`.`class_id`
) as `sum_id`
from
`student_class`
后话
- 使用withCount进行查询
sum
、avg
的时候,在function
中的使用selectRaw
无效的,应该使用DB::raw
这种形式 - 一定要是用
as
+name
,这里的name决定的显示结果中的字段名称 - 可以再上进行统计查询之后使用
having
进行再次筛选,还可以使用orderBy
进行排序操作 - 如果指定
select
个别字段,一定要将select
放在withCount
的前面,放在后面的话会显示不出withCount
的字段信息 - 如果想用原生的方法实现withCount的效果的,采用以下代码
$result = StudentClass::select('id',DB::raw('(select count(id) from student where student.class_id=student_class.id) as sum_count'))