Eloquent count distinct 返回错误的总数

Posted

技术标签:

【中文标题】Eloquent count distinct 返回错误的总数【英文标题】:Eloquent count distinct returns wrong totals 【发布时间】:2014-07-04 13:42:53 【问题描述】:

我对 eloquent 如何制定我无法访问的查询有疑问。当做类似的事情时

$model->where('something')
->distinct()
->paginate();

eloquent 运行一个查询来获取总数,查询看起来像

select count(*) as aggregate from .....

问题是,如果你在查询中使用 distinct,你想要类似

select count(distinct id) as aggregate from .....

得到正确的总数。但 Eloquent 并没有这样做,因此返回了错误的总数。获得不同计数的唯一方法是通过查询构建器传递一个参数,例如 ->count('id') 在这种情况下它将添加它。问题是这个查询是自动生成的,我无法控制它。

有没有办法欺骗它在计数查询中添加不同的?

P.S 深入挖掘构建器代码,我们发现一个 IF 语句要求在 count() 方法上提供一个字段,以便将 distinct 属性添加到计数中。 Illuminate\Database\Query\Grammars\BaseGrammar@compileAggregate

if ($query->distinct && $column !== '*')

   $column = 'distinct '.$column;

return 'select '.$aggregate['function'].'('.$column.') as     aggregate';

PS1 我知道在 SQL 中你可以进行分组,但由于我急于加载东西,所以这不是一个好主意,因为它会在每个其他查询中添加一个 IN(找到的 id 数)显着减慢速度。

【问题讨论】:

顺便说一句,你用的是什么版本的 Laravel? 【参考方案1】:

我遇到了完全相同的问题并找到了两个解决方案:

坏的:

$results = $model->groupBy('foo.id')->paginate();

它可以工作,但如果行数很多(我的情况就是这样),它会消耗太多的内存(和时间)。

更好的:

$ids = $model->distinct()->pluck('foo.id');
$results =  $query = $model->whereIn('foo.id', $ids)->paginate();

我尝试了 100k 结果,完全没有问题。

【讨论】:

【参考方案2】:
$model->where('something')->distinct()->count('id')->paginate();

【讨论】:

【参考方案3】:

这似乎是一个更广泛的问题,在这里讨论:

https://github.com/laravel/framework/issues/3191 https://github.com/laravel/framework/pull/4088

在下一个 Laravel 版本发布修复程序之前,您始终可以尝试使用原始表达式,如下所示(我没有测试它,但应该可以)

$stuff = $model->select(DB::raw('distinct id as did'))
  ->where('whatever','=','whateverelse')
  ->paginate();

参考:http://laravel.com/docs/queries#raw-expressions

【讨论】:

试过了,还是不行。深入挖掘构建器代码,我们发现一个 IF 语句要求在 count() 方法上提供一个字段,以便将 distinct 属性添加到计数中。 Illuminate\Database\Query\Grammars\BaseGrammar@compileAggregate if ($query->distinct && $column !== '*') $column = 'distinct '.$column; return 'select '.$aggregate['function'].'('.$column.') as aggregate'; 正如我在评论中写给你的,你使用的是什么版本的 Laravel?在问题线程中,一些人报告说:With the current version of laravel (4.1) we are having to work around this problem by resorting to using DB::raw() queries for accurate pagination results when distinct() is used. 这就是我的建议的来源。

以上是关于Eloquent count distinct 返回错误的总数的主要内容,如果未能解决你的问题,请参考以下文章

Laravel ELOQUENT 问题中的 DISTINCT

count和distinct

Laravel Eloquent 中的 SQL 查询子字符串

为啥 COUNT(DISTINCT (*)) 不起作用?

countDistinct 和 distinct.count 的区别

COUNT(DISTINCT) 和 COUNT(*) + GROUP BY 给出不同的结果