Laravel - 将 `SQL_CALC_FOUND_ROWS` 与预加载关系一起使用 returns 错误计数
Laravel - Using `SQL_CALC_FOUND_ROWS` with eager-loaded relationship returns wrong count
在我的 Laravel 应用程序中,我正在对模型 (ModelA
) 进行普通查询,同时使用 SQL_CALC_FOUND_ROWS
然后执行 SELECT FOUND_ROWS()
来检索自第一个查询使用 LIMIT
和 OFFSET
.
以来的所有记录数
这工作得很好,但现在我已经在上面查询的模型中添加了关系,如果我执行相同的查询但使用 with->('modelB')
,则此查询将在初始查询之后执行,并且在 SELECT FOUND_ROWS()
之前,所以我得到了 ModelB
结果的计数,而不是我预期的 ModelA
。
有没有办法在我获得第一个(主要)查询的计数而不是关系的情况下按需要进行这项工作?
例如这很好用:
$query = ModelA::select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
// conditional ->where()'s
$query->skip(intval($skip))
->take(intval($take))
->orderBy($column, $dir);
$results = $query->get();
$total = DB::select(DB::raw("SELECT FOUND_ROWS() AS 'total';"))[0]->total;
但将第一行更改为:
$query = ModelA::with('modelB')
->select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
一种解决方法是不预先加载并单独获取每个关系,但是当我稍后在代码中循环遍历结果时,每个结果都有一个查询。
ModelA::with('modelB')
导致 2 个基础 table 中的 join
。如果 modelB
中有多个记录对应 modelA
中的单个记录,则查询 return 的记录数可能比 [=13] 中的记录数多=]. SQL_CALC_FOUND_ROWS
return 是整个查询中的记录数,您不能将其限制为查询中的单个 table。
您要么分别计算 modelA
记录和 return 那个数字,要么您需要 select 来自模型 A 的 table 和 [=15= 的子查询中的数据] 包含在子查询中。我会去单独计数。简单明了。
通过 FOUND_ROWS()
可用的行计数是暂时的,并且不会在 SELECT SQL_CALC_FOUND_ROWS
语句之后的语句之后可用。如果以后需要引用该值,保存...
Eloquent's eager loading 将导致为 with
方法中的每个关系执行额外的 select 语句。
因此 FOUND_ROWS()
返回最后一个 SELECT
语句的计数,即急切加载的关系。
要解决这个问题,您可以使用 lazy eager loading。而不是:
$books = App\Book::with('author.contacts')->get();
使用:
$books = App\Book::all();
$count = DB::select(DB::raw('SELECT FOUND_ROWS()'));
$books->load('author.contacts');
您也可以使用 Constraining Eager Loads 作为第一个关系。
$total = 0;
$query = ModelA::with([
'modelB' => function () use (&$total) {
$total = (int)DB::select("SELECT FOUND_ROWS() as `row_count`")[0]->row_count;
}
])
->select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
$rows = $query->get();
echo $total;
在我的 Laravel 应用程序中,我正在对模型 (ModelA
) 进行普通查询,同时使用 SQL_CALC_FOUND_ROWS
然后执行 SELECT FOUND_ROWS()
来检索自第一个查询使用 LIMIT
和 OFFSET
.
这工作得很好,但现在我已经在上面查询的模型中添加了关系,如果我执行相同的查询但使用 with->('modelB')
,则此查询将在初始查询之后执行,并且在 SELECT FOUND_ROWS()
之前,所以我得到了 ModelB
结果的计数,而不是我预期的 ModelA
。
有没有办法在我获得第一个(主要)查询的计数而不是关系的情况下按需要进行这项工作?
例如这很好用:
$query = ModelA::select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
// conditional ->where()'s
$query->skip(intval($skip))
->take(intval($take))
->orderBy($column, $dir);
$results = $query->get();
$total = DB::select(DB::raw("SELECT FOUND_ROWS() AS 'total';"))[0]->total;
但将第一行更改为:
$query = ModelA::with('modelB')
->select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
一种解决方法是不预先加载并单独获取每个关系,但是当我稍后在代码中循环遍历结果时,每个结果都有一个查询。
ModelA::with('modelB')
导致 2 个基础 table 中的 join
。如果 modelB
中有多个记录对应 modelA
中的单个记录,则查询 return 的记录数可能比 [=13] 中的记录数多=]. SQL_CALC_FOUND_ROWS
return 是整个查询中的记录数,您不能将其限制为查询中的单个 table。
您要么分别计算 modelA
记录和 return 那个数字,要么您需要 select 来自模型 A 的 table 和 [=15= 的子查询中的数据] 包含在子查询中。我会去单独计数。简单明了。
通过 FOUND_ROWS()
可用的行计数是暂时的,并且不会在 SELECT SQL_CALC_FOUND_ROWS
语句之后的语句之后可用。如果以后需要引用该值,保存...
Eloquent's eager loading 将导致为 with
方法中的每个关系执行额外的 select 语句。
因此 FOUND_ROWS()
返回最后一个 SELECT
语句的计数,即急切加载的关系。
要解决这个问题,您可以使用 lazy eager loading。而不是:
$books = App\Book::with('author.contacts')->get();
使用:
$books = App\Book::all();
$count = DB::select(DB::raw('SELECT FOUND_ROWS()'));
$books->load('author.contacts');
您也可以使用 Constraining Eager Loads 作为第一个关系。
$total = 0;
$query = ModelA::with([
'modelB' => function () use (&$total) {
$total = (int)DB::select("SELECT FOUND_ROWS() as `row_count`")[0]->row_count;
}
])
->select([DB::raw("SQL_CALC_FOUND_ROWS *")])
->where('active', 1);
$rows = $query->get();
echo $total;