1

我想限制使用可包含的更深关联返回的字段。

我的联想:

游戏有很多评论

分页和可包含的代码:

$this->paginate = array(
            'conditions' => $conditions,
            'fields' => array(
                'Game.id', 'Game.name',
                'Publisher.id', 'Publisher.name'
            ),
            'contain' => array(
                'Game' => array(                     
                    'Review' => array(
                        'fields' => array('Review.id', 'ROUND(AVG(Review.score),1)')
                    )
                ),
            )
        );
$games = $this->paginate('Game');

当前,Review返回表中的所有字段。'ROUND(AVG(Review.score),1)'永远不会返回。如何指定要从Review关联返回的字段?


SQL使用@theJetzah 的答案转储两个搜索结果。第一个是搜索结果为一场比赛,第二个是搜索返回三场比赛。

SELECT `Review`.`id`, `Review`.`review_text`, `Review`.`score`, `Review`.`user_id`, `Review`.`game_id`, `Review`.`created`, `Review`.`platform_id`, (ROUND(AVG(`Review`.`score`),1)) AS `Review__average_score` FROM `videogamedb`.`reviews` AS `Review` WHERE `Review`.`game_id` = (55)

SELECT `Review`.`id`, `Review`.`review_text`, `Review`.`score`, `Review`.`user_id`, `Review`.`game_id`, `Review`.`created`, `Review`.`platform_id`, (ROUND(AVG(`Review`.`score`),1)) AS `Review__average_score` FROM `videogamedb`.`reviews` AS `Review` WHERE `Review`.`game_id` IN (55, 56, 57)
4

2 回答 2

0

我认为您的阵列配置有点错误,请尝试:

$this->paginate = array(
    'Game' => array(
        'conditions' => $conditions,
        'fields' => array(
            'Game.id', 'Game.name',
            'Publisher.id', 'Publisher.name'
        ),
        'contain' => array(
            'Review' => array(
                'fields' => array('Review.id', 'ROUND(AVG(Review.score),1)')
            )
        )
    )
);
$games = $this->paginate('Game');

顺便说一句,根据个人经验,在查询中指定字段并不总是加快速度(当然对于少量字段),假设这是这样做的动机。它确实减少了内存占用,但这仅与记录的原始大小和返回的记录数有关。

于 2013-05-06T20:52:26.243 回答
0

不是一个完整的答案,而是试图让它工作:)

方法 1(更新:Containable 不支持“分组依据”)

首先,尝试将“游戏”模型添加到$uses控制器的数组中,如果尚未包含它,并重新组织分页数组(如 Sam 之前建议的那样),以便您对游戏进行分页模型本身。

然后,为计算的分数创建一个虚拟字段可能会有所帮助,但需要对'Review'的结果进行分组,否则您将无法计算平均分数。

我无法对此进行测试,但可能值得一试

像这样的东西;

public $uses = array(
    'Game',
    // other models
);

public function myfunction()
{
    $this->Game->Review->virtualFields['average_score'] = 'ROUND(AVG(Review.score),1)';

    $this->paginate = array(
        'Game' => array(
            'fields' => array(
                'Game.id',
                'Game.name',
                'Publisher.id',
                'Publisher.name'
            ),
            'contain' => array(
                'Review' => array(
                    'fields' => array(
                        'Review.game_id,
                        'Review.average_score',
                    ),
                    'group' => array(
                        'Review.game_id,
                    ),
                )
            )
        )
    );

    // Conditions can be passed to paginate,
    // that way you can specify 'paginate' at
    // one place and don't have to modify it
    // to include the conditions
    $games = $this->paginate('Game', $conditions);
}

替代方法:使用连接和数据库视图

显然, Containable 行为不喜欢 group-by 子句。有关更多信息,请参阅此票证:可包含的行为未实现“组”选项

CakePHP 允许你手动指定一个连接:Joining Tables

为了简化事情并避免必须为所有字段添加“分组依据”,请在您的数据库中创建一个简单的数据库视图;

CREATE VIEW review_scores AS
   SELECT 
       game_id, 
       ROUND(AVG(score),1) AS average_score,
       COUNT(id) AS total_reviews
   FROM
       reviews
   GROUP BY
      game_id;

如果您对此不熟悉;数据库“视图”基本上是一个“存储查询”,可以像访问常规表一样访问它。请参阅创建视图

然后,使用“手动”连接,使用新创建的数据库视图作为源表。在您的情况下,这看起来像这样;

$this->paginate = array(
    'Game' => array(
        'fields' => array(
            'Game.id',
            'Game.name',
            'Publisher.id',
            'Publisher.name',
            'ReviewScore.average_score',
            'ReviewScore.total_reviews',
        ),
        'joins' => array(
            array(
                'table' => 'review_scores',
                'alias' => 'ReviewScore',
                'type'  => 'LEFT',
                'conditions' => array(
                    'ReviewScores.game_id = Game.id',
                )
            )
        )
    )
);

希望这可以帮助

于 2013-05-07T07:07:22.197 回答