【问题标题】:cakephp combine find() queriescakephp 结合 find() 查询
【发布时间】:2013-05-24 05:47:59
【问题描述】:

我还是 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);

【问题讨论】:

  • 我认为获取所有信息的方法之一是self join。检查 cakephp 执行此操作的方式。

标签: cakephp


【解决方案1】:

由于所有查询都使用不同的条件,因此无法将它们组合成一个单个查询。这不是 CakePHP 的限制,使用常规 SQL 也不允许您这样做,除非您打算使用子查询或一些 calculated fields (SELECT CASE WHEN points &gt; 0 AND date &gt; .... THEN points ELSE 0 END CASE AS gainedPoint) 但这不会提供 任何好处 em>(性能方面)

优化

为了优化(和清理)您的代码,可以进行一些改进;

首先,要获取单个字段的值,您可以使用Model::field()。这将只返回字段的普通 value,而不是包含该值的 array

例如:

$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());

这将明显减少 Controller 中的代码量(“精益控制器,胖模型”),这始终是一种很好的做法。

为您的数据库添加相关索引

如果性能很重要,您可以通过向数据库添加正确的索引来大幅提高这些查询的性能,尤其是在计算大量记录的总数时。

详细描述这个超出了这个问题的范围,但这里有一些提示; How MySQL uses indexesCREATE INDEX SYNTAX

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 2019-09-07
    相关资源
    最近更新 更多