我仍然是Cakephp的新手我有3个查找相同模型的查询,我试图将它们组合成一个。通过访问数据的蛋糕方式很难找到它。特别是他们有不同的发现条件。也许它无法完成。
Cakephp版本2.3.5
// Count Total Members
$totalMemebers = $this->Member->find('count');
$this->set('totalMemebers', $totalMemebers);
// SUM total points gained for the last 7 days (positive values)
$this->Member->Point->virtualFields['gainedTotal'] = 'SUM(Point.points)';
$gainedTotal = $this->Member->Point->find('all', array(
'recursive'=> -1,
'fields' => array('gainedTotal'),
'conditions'=>array(
'Point.points >'=>0,
'Point.date >' => date('Y-m-d', strtotime("-1 weeks")))
)
);
$this->set('gainedTotal', $gainedTotal);
// SUM total points redeemed for the last 7 days (negative values)
$this->Member->Point->virtualFields['redeemedTotal'] = 'SUM(Point.points)';
$redeemedTotal = $this->Member->Point->find('all', array(
'recursive'=> -1,
'fields' => array('redeemedTotal'),
'conditions'=>array(
'Point.points <'=>0),
'Point.date >' => date('Y-m-d', strtotime("-1 weeks"))
)
);
$this->set('redeemedTotal', $redeemedTotal);
答案 0 :(得分:3)
由于所有查询都使用不同的条件,因此无法将它们组合到单个查询中。这不是CakePHP的限制,使用常规SQL也不允许你这样做,除非你打算使用子查询或某些calculated fields(SELECT CASE WHEN points > 0 AND date > .... THEN points ELSE 0 END CASE AS gainedPoint
),但这将提供没有好处(表现明智)
为了优化(并清理)您的代码, 可以进行一些改进;
首先,要获取单个字段的值,您可以使用Model::field()
。这将只返回字段的普通值,而不是包含该值的数组。
例如:
$this->Member->Point->virtualFields['gainedTotal'] = 'SUM(Point.points)';
$gainedTotal = $this->Member->Point->field('gainedTotal', array(
'Point.points >'=>0,
'Point.date >' => date('Y-m-d', strtotime("-1 weeks"))
));
$this->set('gainedTotal', $gainedTotal);
这是你应该做的一般事情。将这些查询移动到您的模型。这将使您的代码更清洁并且更好地维护。此外,您的查询将更容易重复使用,最后,您将能够单元测试查询。
class Point extends AppModel
{
// general stuff/properties here
/**
* Returns the SUM total points gained for
* the last 7 days (positive values)
*
* @return int Gained total for all members
*/
public function gainedTotal()
{
this->virtualFields['gainedTotal'] = 'SUM(points)';
$gainedTotal = $this->field('gainedTotal', array(
'points >'=>0,
'date >' => date('Y-m-d', strtotime("-1 weeks"))
));
// remove the virtualField to prevent it being used
// in subsequent queries
unset($this->virtualFields['gainedTotal']);
return (int)$gainedTotal;
}
}
而且,在你的控制器中,只需这样做:
$this->set('gainedTotal', $this->Member->Point->gainedTotal());
这显然会减少控制器内部的代码量(“瘦控制器,胖模型”),这总是很好的做法。
如果 重要,则可以通过向数据库添加正确的索引来大规模提高这些查询的性能,尤其是在计算大量记录的总计时。
详细描述这个问题超出了这个问题的范围,但这里有一些指示; How MySQL uses indexes和CREATE INDEX SYNTAX