【问题标题】:Using multiple joins in a Laravel statement overrides values在 Laravel 语句中使用多个连接会覆盖值
【发布时间】:2019-08-07 10:30:36
【问题描述】:

我正在尝试创建一个 Laravel 语句,它应该为每个用户返回正确的值,以获取答案数量和问题数量,如下所示:

$users = User::join('user_answers', 'users.id', '=', 'users_answers.user_id')
        ->join('user_questions', 'users.id', '=', 'user_questions.user_id')
        ->select(
            'users.id',
            'users.username',
            DB::raw('COUNT(user_answers.user_id) AS answers'),
            DB::raw('COUNT(user_questions.user_id) AS questions')
        )
        ->groupBy('users.id');

注意:groupBy 是必需的,因为它在 DataTables 中使用,否则它将只显示一行。

当我尝试:

dd($users->first());

我得到的是这样的:

如您所见,出于某种原因,问题和答案的值相同,并且不正确。我想连接有某种重叠。

例如,如果我删除其中一个联接,只保留其中一列,则数字会正确显示,如下所示:

老实说,我在这里很迷茫,希望能得到一些帮助。

谢谢!

【问题讨论】:

  • 计数相乘 (1412 * 5 = 7060),因为您加入了不相关的问题和答案。
  • 我认为你不应该在 select 中使用 DB::raw() 你可以附加 where 子句。
  • 我会使用集合来代替加入、db::raw() 和选择
  • @senty 将 1412 个答案提取到集合中只是为了获得计数?这将加速全球变暖;-)
  • 快速和“肮脏”的修复将是COUNT(DISTINCT user_answers.id) AS answers

标签: php mysql laravel join eloquent


【解决方案1】:

我很久没有使用Eloquent了,所以不知道有没有“雄辩”的方式可以用一个查询来做到这一点。但在 SQL 中,我会在 SELECT 子句中使用相关子查询:

$users = User::select(
            'users.id',
            'users.username',
            DB::raw('(
                SELECT COUNT(*)
                FROM user_answers
                WHERE users_answers.user_id = users.id
            ) AS answers'),
            DB::raw('(
                SELECT COUNT(*)
                FROM user_questions
                WHERE user_questions.user_id = users.id
            ) AS questions'),
        );

【讨论】:

  • 如果可以通过 Eloquent 构建它,我会考虑一个选项。谢谢!
  • @MichaelNaidis 查看其他答案 - 就是这样。
【解决方案2】:

我会使用Eloquent's relational methods 来构建它。甚至还有一个 withCount() method 可以用来构建查询。

关系方法类似于:

public function answers()
{
    return $this->hasMany(\App\Answer::class);
}

使用数据透视表命名要记住的一件事是Laravel expects the tables to be named alphabetically。所以对于many-to-many relationship,它会期望枢轴被命名为answer_user。但是,您可以在模型的关系方法中定义自定义数据透视表名称。

一旦你在你的模型中设置了关系方法,那么你应该能够构造一个类似于下面的查询:

User::withCount(['answers', 'questions'])->get();

一旦你开始工作,你就可以使用 select 语句进行约束。

【讨论】:

  • 这就是我的回答中“雄辩的方式”的意思。它可能会只使用一行代码生成完全相同的查询。
  • 我喜欢你和你一起去的地方......但是 ORM :)
  • 谢谢!我不知道 withCount()。
  • 这里非常简洁的解决方案!感谢withCount()
猜你喜欢
  • 2017-07-01
  • 1970-01-01
  • 2016-06-21
  • 2018-05-13
  • 2021-11-06
  • 2017-11-03
  • 2021-10-26
  • 2018-12-16
  • 2021-07-02
相关资源
最近更新 更多