Использование подзапроса count в CakePHP ORM - PullRequest
0 голосов
/ 21 мая 2019

Я просматриваю документы CakePHP и нигде не вижу, чтобы объяснить, как вы выполняете подзапрос в операторе MySQL.По сути, я хотел бы подсчитать количество кредитов, которые каждый пользователь имеет в качестве поля, но в данный момент он суммирует суммы кредитов для всех пользователей в одном поле:

   $this->Users->find()
       ->contain(['Plans','Products'])
       ->contain('Credits', function ($q) {
           return $q->select(['count' => $q->func()->count('*')]);
       })->group(['Users.id']);

Запрос, который я пытаюсь выполнитьсоздать больше похоже на:

SELECT *, (SELECT COUNT(*) FROM credits Credits WHERE Credits.user_id = Users.id) as credit_count FROM users Users group by Users.id ASC

1 Ответ

1 голос
/ 22 мая 2019

Содержащие hasMany связи всегда будут извлекаться в отдельном запросе, и именно здесь будут применяться условия, которые вы определяете в обратном вызове содержимого (проверьте вкладку Sql Log в DebugKit ).

Для получения искомых результатов необходимо либо присоединиться к ассоциации, и подсчитать Credits в том же запросе, что-то вроде этого:

$this->Users
    ->find()
    ->select(function(\Cake\ORM\Query $q) {
        return ['count' => $q->func()->count('Credits.id')]
    })
    ->select($this->Users)
    ->contain(['Plans','Products'])
    ->leftJoinWith('Credits')
    ->group(['Users.id']);

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

$subquery = $this->Users->Credits
    ->find()
    ->select(function(\Cake\ORM\Query $q) {
        return ['count' => $q->func()->count('Credits.id')]
    })
    ->where(function (\Cake\Database\Expression\QueryExpression $exp) {
        return $exp->equalFields('Credits.user_id', 'Users.id'):
    });

$this->Users
    ->find()
    ->select(['count' => $subquery])
    ->select($this->Users)
    ->contain(['Plans','Products']);

См. Также

...