Как применить условие «где» к среднему результату функции без второго выбора? - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть приложение Laravel 6. Я хочу использовать eloquent для сбора только тех сотрудников, чей уровень занятости равен true.

Вопрос в том, как применить предложение where к результатам функции avg без второго выбора в Eloqunt. ? Например, что-то вроде этого:

SELECT
    `employees`.*,
    AVG(responses.text_answer) > 4.6 AS engaged
FROM
    `employees`
INNER JOIN `responses` AS `responses`
ON
    `responses`.`employee_id` = `employees`.`id`
INNER JOIN `survey_questions` AS `surveyQuestions`
ON
    `surveyQuestions`.`id` = `responses`.`survey_question_id`
INNER JOIN `questions` AS `questions`
ON
    `questions`.`id` = `surveyQuestions`.`question_id`
WHERE
    engaged = 1 AND `questions`.`question_type_id` = '6S'
GROUP BY
    `employees`.`id`

Но проблема в том, что engaged в состоянии WHERE здесь не распознано и MySQL показывает:

Неизвестный столбец «занят» в 'предложении where'

Часть моего красноречивого утверждения выглядит следующим образом:

public function engaged()
    {
        return $this->relatedToMany(QuestionType::class, function(Builder $query){
            if(!$this->joined($query, 'responses')){
                $query->join(
                    'responses AS responses',
                    'responses.employee_id',
                    '=',
                    'employees.id',
                    'inner'
                );
            }
            if(!$this->joined($query, 'survey_questions')){
                $query->join(
                    'survey_questions AS surveyQuestions',
                    'surveyQuestions.id',
                    '=',
                    'responses.survey_question_id',
                    'inner'
                );
            }
            if(!$this->joined($query, 'questions')){
                $query->join(
                    'questions AS questions',
                    'questions.id',
                    '=',
                    'surveyQuestions.question_id',
                    'inner'
                );
            }
            $query->where('questions.question_type_id', '6S');
            $query->select('employees.*', \DB::raw('AVG(`responses`.`text_answer`) >= 4.6 AS `engaged`'));
            $query->groupBy('employees.id');
        });
    }

И предложение where применяется следующим образом:

public function filterEngaged(EloquentBuilder $query, $method, $clauseOperator, $value, $column, $table)
{
    call_user_func([$query, $method], $column, $value);
    // $method = 'where', $column = 'engaged' , $value = 1
}

1 Ответ

1 голос
/ 03 февраля 2020

Нельзя применить условие WHERE к статистической функции. Базы данных сначала оценивают предложение WHERE, а затем агрегируют.

Вместо этого вы можете использовать для этого предложение HAVING (оно оценивается после предложения GROUP BY).

Поэтому вам нужно изменить это:

WHERE 
    engaged = 1 AND `questions`.`question_type_id` = '6S'
GROUP BY
    `employees`.`id`

На:

WHERE 
    `questions`.`question_type_id` = '6S'
GROUP BY
    `employees`.`id`
HAVING
    engaged = 1

В Лавареле это должно выглядеть так:

$query->where('questions.question_type_id', '6S');
$query->select('employees.*', \DB::raw('AVG(`responses`.`text_answer`) >= 4.6 AS `engaged`'));
$query->groupBy('employees.id');
$query->havingRaw('engaged = 1');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...