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() 来检索自第一个查询使用 LIMITOFFSET.

以来的所有记录数

这工作得很好,但现在我已经在上面查询的模型中添加了关系,如果我执行相同的查询但使用 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;