查询来自 Eloquent 的计数
Querying count from Eloquent
我在 eloquent 中有一个查询正确地计算了这里应有的计数:
$query = A::withCount(
['bs' =>
function ($query) use ($from, $to) {
$query->where(function ($query) use ($from) {
$query->whereDate('start', '<', $from)
->whereDate('end', '>', $from);
})->orWhere(function ($query) use ($to) {
$query->whereDate('start', '<', $to)
->whereDate('end', '>', $to);
})->orWhere(function ($query) use ($from, $to) {
$query->whereDate('start', '>', $from)
->whereDate('end', '<', $to);
});
}])
->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
->where('cmp3', '<=', $request->cmp3)
->where('cmp4', '<=', $request->cmp4)
->with('more_relations');
return AResource::collection($query->paginate(5));
这转到 API 控制器。我将其用于 Vue 的前端分页。我想使用计数过滤掉所有 bs_count
为 0 的 A
,但是链接 where 子句不起作用,因为它是一个聚合,并且它 returns 一个错误因为找不到名为 bs_count
的列。我发现解决方案是使用 having
子句。我找到了这段代码,但是当我尝试转换它时,它不起作用,返回相同的错误,找不到名为 bs_count
.
的列
DB::table('bs')
->select('*', DB::raw('COUNT(*) as bs_count'))
->groupBy('a_id')
->having('bs_count', '=' , 0);
这没有在计数上添加额外的查询,因为我想先试试看它是否有效,但事实并非如此。
having
子句是否正确?我想我需要使用 Eloquent 而不是 DB::table()
语法,因为资源构建器使用模型结构来构建资源响应。
总而言之,我正在尝试使用我在第一个查询中计算的计数,并针对它进行查询:where bs_count = 0
。有没有办法在 Laravel 中执行此操作并且仍然能够将结果传递给 API 资源?
使用 HAVING
子句是正确的方法。
问题是 Laravel 分页本身不支持 HAVING
子句。
您必须手动创建 pagniator:
How to use paginate() with a having() clause when column does not exist in table
您使用 DB
的测试查询不起作用,因为分组时您不能 select 所有列:
->select('a_id', DB::raw('COUNT(*) as bs_count'))
正如我发现的那样,Laravel 确实有一个 built-in 解决方案。 From the docs,我找到了函数whereHas()
和whereDoesntHave()
。这些函数允许您传递一个闭包,以根据它在幕后进行的计数来过滤行。我如何调整我以前的解决方案是:
$query = A::whereDoesntHave(
'bs',
function ($query) use ($from, $to) {
$query->where(function ($query) use ($from) {
$query->whereDate('start', '<', $from)
->whereDate('end', '>', $from);
})->orWhere(function ($query) use ($to) {
$query->whereDate('start', '<', $to)
->whereDate('end', '>', $to);
})->orWhere(function ($query) use ($from, $to) {
$query->whereDate('start', '>', $from)
->whereDate('end', '<', $to);
});
)
->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
->where('cmp3', '<=', $request->cmp3)
->where('cmp4', '<=', $request->cmp4)
->with('more_relations');
return AResource::collection($query->paginate(5));
这会根据传递的查询自动计算 B
,并且只有 returns 行的计数为零,这正是我所需要的。
我在 eloquent 中有一个查询正确地计算了这里应有的计数:
$query = A::withCount(
['bs' =>
function ($query) use ($from, $to) {
$query->where(function ($query) use ($from) {
$query->whereDate('start', '<', $from)
->whereDate('end', '>', $from);
})->orWhere(function ($query) use ($to) {
$query->whereDate('start', '<', $to)
->whereDate('end', '>', $to);
})->orWhere(function ($query) use ($from, $to) {
$query->whereDate('start', '>', $from)
->whereDate('end', '<', $to);
});
}])
->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
->where('cmp3', '<=', $request->cmp3)
->where('cmp4', '<=', $request->cmp4)
->with('more_relations');
return AResource::collection($query->paginate(5));
这转到 API 控制器。我将其用于 Vue 的前端分页。我想使用计数过滤掉所有 bs_count
为 0 的 A
,但是链接 where 子句不起作用,因为它是一个聚合,并且它 returns 一个错误因为找不到名为 bs_count
的列。我发现解决方案是使用 having
子句。我找到了这段代码,但是当我尝试转换它时,它不起作用,返回相同的错误,找不到名为 bs_count
.
DB::table('bs')
->select('*', DB::raw('COUNT(*) as bs_count'))
->groupBy('a_id')
->having('bs_count', '=' , 0);
这没有在计数上添加额外的查询,因为我想先试试看它是否有效,但事实并非如此。
having
子句是否正确?我想我需要使用 Eloquent 而不是 DB::table()
语法,因为资源构建器使用模型结构来构建资源响应。
总而言之,我正在尝试使用我在第一个查询中计算的计数,并针对它进行查询:where bs_count = 0
。有没有办法在 Laravel 中执行此操作并且仍然能够将结果传递给 API 资源?
使用 HAVING
子句是正确的方法。
问题是 Laravel 分页本身不支持 HAVING
子句。
您必须手动创建 pagniator:
How to use paginate() with a having() clause when column does not exist in table
您使用 DB
的测试查询不起作用,因为分组时您不能 select 所有列:
->select('a_id', DB::raw('COUNT(*) as bs_count'))
Laravel 确实有一个 built-in 解决方案。 From the docs,我找到了函数whereHas()
和whereDoesntHave()
。这些函数允许您传递一个闭包,以根据它在幕后进行的计数来过滤行。我如何调整我以前的解决方案是:
$query = A::whereDoesntHave(
'bs',
function ($query) use ($from, $to) {
$query->where(function ($query) use ($from) {
$query->whereDate('start', '<', $from)
->whereDate('end', '>', $from);
})->orWhere(function ($query) use ($to) {
$query->whereDate('start', '<', $to)
->whereDate('end', '>', $to);
})->orWhere(function ($query) use ($from, $to) {
$query->whereDate('start', '>', $from)
->whereDate('end', '<', $to);
});
)
->whereBetween('cmp1', [$min_cmp1, $max_cmp1])
->whereBetween('cmp2', [$min_cmp2, $max_cmp2])
->where('cmp3', '<=', $request->cmp3)
->where('cmp4', '<=', $request->cmp4)
->with('more_relations');
return AResource::collection($query->paginate(5));
这会根据传递的查询自动计算 B
,并且只有 returns 行的计数为零,这正是我所需要的。