【问题标题】:CakePHP GROUP BY with WHERE and COUNT on HATBM tableCakePHP GROUP BY 与 HATBM 表上的 WHERE 和 COUNT
【发布时间】:2012-11-26 12:03:34
【问题描述】:

虽然我知道 find() 上的 groupcontainfieldsorder 选项,但我似乎无法使用 CakePHP 2.2.3 进行以下查询:

SELECT `User`.*, SUM(`Influence`.`id`) AS matches
FROM `db`.`users` AS `User` 
    LEFT JOIN `db`.`influences_users` AS `InfluencesUser` ON (`User`.`id` = `InfluencesUser`.`user_id`) 
    LEFT JOIN `db`.`influences` AS `Influence` ON (`InfluencesUser`.`influence_id` = `Influence`.`id`)
WHERE 1 = 1
AND `Influence`.`id` IN (1, 2, 3, 4)
GROUP BY `User`.`id` 
ORDER BY COUNT(`Influence`.`id`) DESC

基本上,我正在尝试使用Influences 表上的COUNT() 函数检索具有Influences 1、2、3 和4 的Users 数组,然后按COUNT() DESC 对它们进行排序.

在 CakePHP 中是否有一种简洁的方法(我不想使用任何技巧或函数,如 Model::query())?


编辑: 实际上不是SUM(),而是COUNT(),尽管我没有对我的问题做出任何改变。 p>

【问题讨论】:

  • 尝试在此处使用虚拟字段 - 使查询方式在之后更具可读性和可用性。
  • @mark 我想到了,但是怎么做呢?虚拟字段不是用于当前模型中的数据吗?我只需要这个特定功能中的SUM() 字段。如果我找到一种使用虚拟字段的方法,它不会使模型更重,而是每次我使用模型时都添加这个字段吗?

标签: cakephp count group-by has-and-belongs-to-many cakephp-2.2


【解决方案1】:

您可以使用动态添加虚拟字段,仅用于下一个查询

$this->virtualFields['matches'] = 'SUM(Influence.id)';

然后你可以直接在你的结果数组中使用它:

echo $user['User']['matches']; // if you query on the User model that is

您也可以在您的订单/条件等上使用它:

'order' => array('User__matches' => 'DESC')

不过,您需要处理模型,该模型将所有其他模型都设为“belongsTo”! 所以使用“InfluencesUser”并包含“Influence”和“User”

所以在你的情况下:

$this->User->InfluencesUser->virtualFields['matches'] = 'SUM(Influence.id)';
...
$results = $this->User->InfluencesUser->find(...)

echo $result['InfluencesUser']['matches']; //in the view

'order' => array('InfluencesUser__matches' => 'DESC')

【讨论】:

  • 我不知道在飞行中做这件事;除非我添加模型名称,否则它会出错,例如$this->User->virtualFields...。虽然这很酷,但它仍然没有真正回答我的问题(除非我没有完全理解你的答案)。
  • 您不能在 hasMany 方向上进行单个查询。您需要查询 hasMany 模型并包含 belongsTo 模型。这样你就可以达到上述目的。我的回答只是在这里一般使用更干净的 virtualFields 方法。
【解决方案2】:

我设法找到了一个解决方案,不是太老套,除非有人有更好的解决方案(当你看到我得到的答案数量时不是很多),这里是:

$this->User->virtualFields['matches'] = 'COUNT(InfluencesUser.influence_id)';
$matches = $this->User->find(
        'all',
        array(
            'joins' => array(
                array(
                    'alias' => 'InfluencesUser',
                    'table' => 'influences_users',
                    'type' => 'LEFT',
                    'conditions' => array(
                        'InfluencesUser.influence_id' => $userInfluences, //$userInfluences contains the list of influences I want to do the restriction on
                        '`InfluencesUser`.`user_id` = `User`.`id`'
                    )
                )
            ),
            'group' => 'User.id',
            'order' => array('User__matches' => 'DESC'),
        ));


我手动加入InfluencesUser 表(我实际上不需要Influence 一个,只需要influence_id 的列表)来制作一张大表。我只需要对join 表执行限制(influence_id),然后我可以执行我的goup bycount() 并将count() 字段附加到我的结果数组中,这要感谢mark's answer

显然我更喜欢使用类似contain 参数的东西,但它似乎不允许我在这种特殊情况下做我可以使用join 实现的目标。

希望这可以为某些人节省一些时间。

【讨论】:

    【解决方案3】:

    子查询怎么样?

    http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#sub-queries

    answered a question 使用这种方法解决 HATBM 问题。对于复杂的查询,这是一种有用的方法。

    【讨论】:

    • 那么在这种特殊情况下你会怎么做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2014-10-22
    • 1970-01-01
    相关资源
    最近更新 更多