【问题标题】:Laravel Eloquent - distinct() and count() not working properly togetherLaravel Eloquent - distinct() 和 count() 不能一起正常工作
【发布时间】: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');

标签: laravel count eloquent distinct


【解决方案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
              ]
              

              【讨论】:

                猜你喜欢
                • 2021-02-05
                • 2018-04-05
                • 1970-01-01
                • 1970-01-01
                • 2017-04-23
                • 1970-01-01
                • 2021-08-18
                • 2022-01-26
                • 1970-01-01
                相关资源
                最近更新 更多