Возможно ли сделать подзапросы в 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 и без использования объединений.
Есть ли решение?
и спасибо заранее.
Сначала найдите дублеты по полям 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);