Использование нескольких объединений в операторе Laravel переопределяет значения - PullRequest
1 голос
/ 16 марта 2019

Я пытаюсь создать оператор 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());

Что я получил, это:

Example

Как видите, значения по каким-то причинам одинаковы для вопросов и ответов и неверны.Я предполагаю, что есть какое-то совпадение с объединениями.

Например, если я удаляю одно из объединений и оставляю только один из столбцов, числа отображаются правильно, например:

Example 2

Я, честно говоря, совершенно растерялся, был бы признателен за помощь.

Спасибо!

Ответы [ 2 ]

3 голосов
/ 16 марта 2019

Я бы использовал реляционные методы Eloquent , чтобы построить это. Есть даже withCount() метод , который вы можете использовать для построения вашего запроса.

Реляционные методы будут выглядеть примерно так:

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

При именовании сводных таблиц следует помнить, что Laravel ожидает, что таблицы будут иметь имена в алфавитном порядке . Так что для отношения «многие ко многим» можно ожидать, что стержень будет называться answer_user. Однако вы можете определить имя пользовательской сводной таблицы в реляционном методе Модели.

Как только вы настроите реляционные методы в своей модели, вы сможете создать запрос, подобный следующему:

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

Как только вы начнете работать, вы можете ограничиться утверждениями select.

3 голосов
/ 16 марта 2019

Я не использовал 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'),
        );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...