子查询ActiveRecord Yii

时间:2011-12-11 21:37:47

标签: php yii subquery yii-cactiverecord

是否可以在Yii中的ActiveRecord中进行子查询?

我有这样的查询:

select * from table1 where table1.field1 in (select table2.field2 from table2)

我目前正在使用以下代码:

object1::model()->findAll(array('condition'=>'t.field1 in (select table2.field2 from table2)'))

[编辑]
我想知道是否有一种方法来构造子查询而不使用SQL,也没有使用连接。

有没有解决方案?

并提前致谢。

3 个答案:

答案 0 :(得分:11)

首先按数据库字段找到双联:

$model=new MyModel('search');
$model->unsetAttributes();

$criteria=new CDbCriteria();
$criteria->select='col1,col2,col3';
$criteria->group = 'col1,col2,col3';
$criteria->having = 'COUNT(col1) > 1 AND COUNT(col2) > 1 AND COUNT(col3) > 1';

获取子查询:

$subQuery=$model->getCommandBuilder()->createFindCommand($model->getTableSchema(),$criteria)->getText();

添加子查询条件:

$mainCriteria=new CDbCriteria();
$mainCriteria->condition=' (col1,col2,col3) in ('.$subQuery.') ';
$mainCriteria->order = 'col1,col2,col3';

使用方法:

$result = MyModel::model()->findAll($mainCriteria);

或者:

$dataProvider = new CActiveDataProvider('MyModel', array(
        'criteria'=>$mainCriteria,
));

来源:http://www.yiiframework.com/wiki/364/using-sub-query-for-doubletts/

答案 1 :(得分:6)

不,没有办法使用Yii的CDbCriteriaCActiveRecord以编程方式构造子查询。看起来Query Builder看起来也不像。

但是,您仍然可以通过几种不同的方式进行子查询:

$results = Object1::model()->findAll(array(
  'condition'=>'t.field1 in (select table2.field2 from table2)')
);

您也可以进行连接(可能会更快,子查询可能会很慢):

$results = Object1::model()->findAll(array(
  'join'=>'JOIN table2 ON t.field1 = table2.field2'
);

您还可以使用findAllBySql执行直接SQL查询:

$results = Object1::model()->findAllBySql('
  select * from table1 where table1.field1 in 
  (select table2.field2 from table2)'
);

但是,你可以至少为这些提供一个漂亮的AR风格界面:

class MyModel extends CActiveRecord {
  public function getResults() {
    return Object1::model()->findAll(array(
      'condition'=>'t.field1 in (select table2.field2 from table2)')
    );
  }
}

这样称呼:

$model = new MyModel();
$results = $model->results;

一个有趣的替代想法是使用查询构建器的CDbCommand或其他东西创建子查询,然后将生成的SQL查询字符串传递给CDbCritera addInCondition()?不确定这是否有效,但可能会:

$sql = Yii::app()->db->createCommand()
  ->select('*')
  ->from('tbl_user')
  ->text;
$criteria->addInCondition('columnName',$sql);

您始终可以扩展基本CDbCriteria类,以便以某种方式处理和构建子查询。可能会发布一个很好的扩展你可以释放! :)

我希望有所帮助!

答案 2 :(得分:0)

我知道这是一个旧帖子,但也许有人(像我一样)仍然需要答案。

与先前的答案有关的小问题。所以,这是我的增强功能:

$model=new SomeModel();
$criteria=new CDbCriteria();
$criteria->compare('attribute', $value);
$criteria->addCondition($condition);
// ... etc
$subQuery=$model->getCommandBuilder()->createFindCommand($model->getTableSchema(),$criteria)->getText();

$mainCriteria=new CDbCriteria();
$mainCriteria->addCondition($anotherCondition);
// ... etc

// NOW THIS IS IMPORTANT 
$mainCriteria->params = array_merge($criteria->params, $mainCriteria->params);

// Now You can pass the criteria:
$result = OtherModel::model()->findAll($mainCriteria);