Yii Relational Query如何提供按类别细分的聚合?

时间:2013-02-10 22:38:57

标签: php sql activerecord yii aggregate-functions

我有Person可以接收多种类型的Income。我希望能够返回SUM收入,按每个Income Type细分。

+---------------+-----------------+
| INCOME TYPE   | SUM AMOUNT      |
+---------------+-----------------+
| Salary        | $934.33         |
| Gambling      |  $27.99         |
| Tips          | $584.00         |
+---------------+-----------------+        

我已经能够获得self::STAT关系查询以提供收到的总收入(1546.32美元),但未按Income Type细分。

因此,我尝试将其作为self::HAS_MANY模型中的Person关系查询,如下所示:

  public function relations() {
     return array(
        'incomes_total' => array(
           self::HAS_MANY,
           'Income',
           'person_id',
           'select' => array('income_type_id', 'SUM(amount) AS total'),
           'group' => "income_type_id"
     ));
  }

这会导致生成以下SQL:

SELECT
  "incomes_total"."income_type_id" AS "t1_c5"
, SUM(amount) AS total
, "incomes_total"."id" AS "t1_c0"
FROM "stwd_income" "incomes_total"
WHERE ("incomes_total"."person_id"=:ypl0)
GROUP BY income_type_id

这非常接近所需的查询。

我无法弄清楚为什么在那里添加了行, "incomes_total"."id" AS "t1_c0"。我不希望这样。它导致CDbException错误:

CDbCommand failed to execute the SQL statement: 
SQLSTATE[42803]: Grouping error: 7 ERROR: column "incomes_total.id" must 
appear in the GROUP BY clause or be used in an aggregate function.

如何实现我需要的查询类型?

更新1: Active Record和自定义SQL查询之间的区别开始变得清晰,而Active Record可能不适合此类任务。

1 个答案:

答案 0 :(得分:1)

我个人不会将ActiveRecord用于非常基本的查询和CRUD。即使存在STAT关系,它们也更适用于简单计数或求和。并且HAS_MANY关系在任何方面都是错误的,因为您不期待一系列模型,是吗?你只需要一个简单的id和sum数组,所以在你的情况下我只需在Person模型中创建一个像这样的方法

private $_salaryInfo;

public function getSalaryInfo()
{
    //cache the value if possible to save unnecessary queries
    if(isset($this->_salaryInfo))
        return $this->_salaryInfo;

    //query database
    $command = Yii::app()->db->createCommand();
    $command->select('income_type_id, SUM(amount)')->where('person_id = '.$this->id)->groupBy('income_type_id');
    return $this->_salaryInfo = $command->queryAll();
}

你现在应该能够做到

foreach($person->salaryInfo as $type_id => $sum)