【问题标题】:Using count subquery within CakePHP ORM在 CakePHP ORM 中使用 count 子查询
【发布时间】:2019-10-07 23:40:06
【问题描述】:

我正在浏览 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

【问题讨论】:

  • Credits 是什么类型的关联? hasMany?
  • @ndm 是的

标签: mysql sql cakephp orm cakephp-3.0


【解决方案1】:

包含的hasMany 关联将始终在单独的查询中检索,这就是将应用您在包含回调中定义的条件的位置(检查DebugKit 的 Sql Log 选项卡)。

要获得您正在寻找的结果,需要加入关联,并在同一查询中计算 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']);

另见

【讨论】:

  • 感谢@ndm,这还会带回没有信用的用户行吗?这就是我在使用 leftJoinWithMatching 等时遇到的问题...... equalFields 看起来特别方便 - 谢谢。
  • @Tim 两者都会返回没有积分的用户,是的。对于第一个示例innerJoinWith 应该避免这种情况,对于第二个示例,您可以使用例如利用HAVING 子句中的子查询结果的条件(在选择大量行时可能不会表现得非常好)。
猜你喜欢
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
  • 2022-01-21
相关资源
最近更新 更多