Подзапросы ActiveRecord Yii

Возможно ли сделать подзапросы в ActiveRecord в Yii?

У меня есть такой запрос:

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 и без использования объединений.

Есть ли решение?

и спасибо заранее.

Solutions Collecting From Web of "Подзапросы ActiveRecord Yii"

Сначала найдите дублеты по полям db:

 $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/

Нет, нет возможности программно построить подзапрос с использованием CDbCriteria Yii и CActiveRecord . Это не похоже на то, что у 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' ); 

Вы также можете выполнить прямой SQL-запрос с помощью findAllBySql :

 $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 Query Builder или что-то еще, а затем просто передать полученную строку запроса SQL в CDbCritera addInCondition() ? Не уверен, что это сработает, но это может:

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

Вы всегда можете расширить базовый класс CDbCriteria для обработки и сборки подзапросов так или иначе. Можете сделать хорошее расширение, которое вы могли бы выпустить! 🙂

Надеюсь, это поможет!

Я знаю, что это старая нить, но, возможно, кому-то (как и мне) все еще нужен ответ.

Есть небольшие проблемы, связанные с предыдущими ответами. Итак, вот мое усовершенствование:

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