Laravel Eloquent - distinct() 和 count() 不能一起正常工作

Posted

技术标签:

【中文标题】Laravel Eloquent - distinct() 和 count() 不能一起正常工作【英文标题】:Laravel Eloquent - distinct() and count() not working properly together 【发布时间】:2015-04-23 11:23:36 【问题描述】:

所以我试图在查询中获取不同 pid 的数量,但返回的值是错误的。

这是我尝试做的:

$ad->getcodes()->groupby('pid')->distinct()->count()

什么返回值“2”,而它应该返回的值应该是“1”。

作为一种解决方法,我正在这样做:

count($ad->getcodes()->groupby('pid')->distinct()->get())

什么工作正常并返回“1”

是否有任何规则使 count 和 distinct 不能在同一个查询上?我发现解决方法有点“重”,我想让原始查询工作:(

【问题讨论】:

您在数据库的示例表中有什么?你想达到什么目标?现在您可能应该在 pid 列中获得不同值的数量,因此如果您的表中有 2 条记录 - 一条 pid 1,第二条 pid 2,count 应该返回 2。 你可以这样简单地用count替换get:$count = DB::table('tablename')->count(DB::raw('DISTINCT pid'));也可以这样做:DB::table('tablename')->distinct('pid')->count('pid'); 【参考方案1】:

以下应该可以工作

$ad->getcodes()->distinct()->count('pid');

【讨论】:

有一个类似的问题,似乎只是省略了groupBy 就可以了。 Distinct 不接受任何参数。在构建查询时调用 distinct() 只会将受保护的布尔值设置为 true,而忽略该参数。 在 L5.1 上,这仍然无法正常工作。使用count() 似乎会禁用或删除distinct()。如整个问题所述,使用groupBy()。编辑:与get() 相比,我发现甚至groupBy() 提供了不同的count(),然后计算结果数组。 @Jason 我和你做了同样的观察。请参阅我的答案以获得解决方案。 distinct() 函数不接受任何参数。您可以将其更改为$ad->getcodes()->distinct()->count('pid');,结果相同。【参考方案2】:

这对我有用,所以 尝试这个: $ad->getcodes()->distinct('pid')->count()

【讨论】:

您好,欢迎来到 SO。回答问题时,请提供有关您提供的代码的其他信息。欢迎这样的贡献,但将来其他人可能会从镜头解释中受益【参考方案3】:

我遇到了类似的问题,并找到了解决方法。

问题在于 Laravel 的查询构建器处理聚合的方式。它采用返回的第一个结果,然后返回“聚合”值。这通常很好,但是当您将 count 与 groupBy 结合使用时,您将返回每个分组项目的计数。所以第一行的聚合只是第一组的计数(所以可能是 1 或 2 之类的低值)。

所以 Laravel 的计数已经结束,但我将 Laravel 查询构建器与一些原始 SQL 结合起来,以获得我分组结果的准确计数。

对于您的示例,我希望以下内容应该有效(并让您避免获取):

$query = $ad->getcodes()->groupby('pid')->distinct();
$count = count(\DB::select($query->toSql(), $query->getBindings()));

如果您想确保不会浪费时间选择所有列,则可以在构建查询时避免这种情况:

 $query = $ad->select(DB::raw(1))->getcodes()->groupby('pid')->distinct();

【讨论】:

【参考方案4】:

还有其他人看到这篇文章,但没有找到其他可行的建议吗?

根据具体查询,可能需要不同的方法。就我而言,我需要计算GROUP BY 的结果,例如

SELECT COUNT(*) FROM (SELECT * FROM a GROUP BY b)

或使用COUNT(DISTINCT b):

SELECT COUNT(DISTINCT b) FROM a

经过一番摸索,我意识到这两个都没有内置的 Laravel 函数。所以最简单的解决方案是使用 DB::rawcount 方法。

$count = $builder->count(DB::raw('DISTINCT b'));

记住,在调用count 之前不要使用groupBy。如果您需要它来获取行,您可以稍后申请groupBy

【讨论】:

$builder 是从哪里来的? @Andrew 您用于查询的 Laravel 查询构建器。例如,一个 Eloquent 对象$books = Book::where(...)->count(...) ->count(DB::raw('DISTINCT b')) 生成与->distinct()->count('b')相同的SQL查询【参考方案5】:

我遇到了同样的问题。

如果你安装了 laravel 调试栏你可以看到查询并且经常看到问题

$ad->getcodes()->groupby('pid')->distinct()->count()

改成

$ad->getcodes()->distinct()->select('pid')->count()

您需要将值设置为不同的返回值。如果您不设置选择字段,它将返回数据库中的所有列,并且所有列都是唯一的。因此,将查询设置为 distinct 并仅选择构成您可能想要添加的“distinct”值的列。 ->select('pid','date') 获取用户一天内的所有唯一值

【讨论】:

【参考方案6】:

这不行吗?

$ad->getcodes()->distinct()->get(['pid'])->count();

请参阅here 进行讨论..

【讨论】:

这不是一个好的解决方案,因为get()调用会执行查询并从数据库返回结果,然后count()在Collection上运行。【参考方案7】:

一个更通用的答案可以节省我的时间,希望其他人:

不起作用(返回所有行的计数):

DB::table('users')
            ->select('first_name')
            ->distinct()
            ->count();

修复:

DB::table('users')
            ->distinct()
            ->count('first_name');

【讨论】:

【参考方案8】:

Distinct 不接受参数,因为它在您的 sql 查询中添加了 DISTINCT,但是,您可能需要定义要选择 distinct 的列名。因此,如果你有 Flight->select('project_id')->distinct()->get() 等同于 SELECT DISTINCT 'project_id' FROM flights,您现在可以添加其他修饰符,例如 count() 甚至是原始的 eloquent 查询。

【讨论】:

【参考方案9】:
$solution = $query->distinct()
            ->groupBy
            (
                [
                    'array',
                    'of',
                    'columns',
                ]
            )
            ->addSelect(
                [
                    'columns',
                    'from',
                    'the',
                    'groupby',
                ]
            )
            ->get();

记住 group by 是可选的,当您希望计数 group by 排除重复的选择值时,这应该在大多数情况下起作用,addSelect 是一个查询构建器实例方法。

【讨论】:

【参考方案10】:

试试这个

$ad->getcodes()->groupby('pid')->distinct()->count('pid')

【讨论】:

【参考方案11】:

您可以根据需要使用以下方式获取唯一数据,如下所示,

$data = $ad->getcodes()->get()->unique('email');

$count = $data->count();

希望这会奏效。

【讨论】:

这将从数据库中提取记录,然后执行计数。那是没有效率的。另一方面,$ad->getcodes()->distinct('pid')->count('pid');现在我们不必实际选择记录,而是可以只计算它们,这样更有效【参考方案12】:

基于Laravel docs for raw queries,我能够获得一个选择字段的计数,以便在产品模型中使用此代码。

public function scopeShowProductCount($query)

    $query->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))
          ->groupBy('pid')
          ->orderBy('count_pid', 'desc');

这个外观在控制器中得到了相同的结果:

$products = DB::table('products')->select(DB::raw('DISTINCT pid, COUNT(*) AS count_pid'))->groupBy('pid')->orderBy('count_pid', 'desc')->get();

两个查询的结果转储如下:

#attributes: array:2 [
  "pid" => "1271"
  "count_pid" => 19
],
#attributes: array:2 [
  "pid" => "1273"
  "count_pid" => 12
],
#attributes: array:2 [
  "pid" => "1275"
  "count_pid" => 7
]

【讨论】:

以上是关于Laravel Eloquent - distinct() 和 count() 不能一起正常工作的主要内容,如果未能解决你的问题,请参考以下文章

php Laravel 5 Eloquent CheatSheet #laravel #eloquent

php [Eloquent CheatSheet] Eloquent #laravel #eloquent的常见查询方法

Laravel - Eloquent 连接

Laravel 从 Raw DB 到 Eloquent

Laravel/Eloquent 建议覆盖 trait 属性?

创建动态的 Eloquent 类 laravel