我有yii驱动的应用程序和大数据记录过滤器,其中包含大而复杂的逻辑。我写了正确的SQL查询并测试了它。
SELECT
c.`customer_id` AS 'customer_id'
, c.`status_id` AS 'status_id'
, c.`customer_name` AS 'customer_name'
, BIT_OR(r2c.`role_id`) AS 'roles_mask'
FROM
`customers` AS c
LEFT JOIN
`roles2customers` AS r2c
ON
c.`customer_id` = r2c.`customer_id`
WHERE
IF( :status_mask = 0
, c.`status_id` = 0
, c.`status_id` & :status_mask <> 0
)
AND c.`customer_id` <> :customer_id
AND c.`customer_name` LIKE concat(:customer_name, '%')
GROUP BY
c.`customer_id`
HAVING
IF( :role_mask = 0
, BIT_OR(r2c.`role_id`) = 0
, BIT_OR(r2c.`role_id`) & :role_mask <> 0
)
ORDER BY
c.`customer_name` ASC
LIMIT
:offset, :count
此查询适用于简单的ActiveRecord方法findAllBySql:
$filtered_records = ModelClass::model()->findAllBySql( $sql, $params );
但我的问题是使用CDbCriteria编写应用程序后端。所以我需要建立正确的标准对象并将其传递给 findAll 方法:
$criteria = new CDbCriteria();
$filtered_records = ModelClass::model()->findAll( $criteria );
我打开了CDBCriteria reference,看到了很多简单的例子,但是......在我的情况下如何通过条件指定JOIN和HAVING操作?
我的代码:
$criteria = new CDbCriteria();
$criteria->condition = "
c.customer_id AS 'customer_id',
c.status_id AS 'status_id',
c.customer_name AS 'customer_name',
BIT_OR(r2c.role_id) AS 'roles_mask'
";
$criteria->offset = $offset;
$criteria->limit = $limit;
// how can I make valid r2c relation and group by via criteria?
// and all another sql parts...
答案 0 :(得分:3)
GROUP BY
和HAVING
部分可以与condition
,offset
和limit
相同的方式直接连接:
$criteria->group ='t.customer_id'
$criteria->having='IF( :role_mask = 0
, BIT_OR(r2c.`role_id`) = 0
, BIT_OR(r2c.`role_id`) & :role_mask <> 0
)'
LEFT JOIN
有点复杂,但可以使用with
完成:
$criteria->with=array(
'roles2customers'=>array(
'alias'=>'r2c',
'joinType'=>'LEFT JOIN',
'condition'=>'
IF( :status_mask = 0
, t.`status_id` = 0
, t.`status_id` & :status_mask <> 0
)
AND t.`customer_id` <> :customer_id
AND t.`customer_name` LIKE concat(:customer_name, '%')
',
)
)
这取决于您在roles2customers
中设置基本关系ModelClass
。