2011-12-11 32 views
7

¿Es posible hacer subconsultas en ActiveRecord en Yii?Sub-consultas ActiveRecord Yii

Tengo una consulta como esta:

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

Actualmente estoy usando el código de barbecho:

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

[Editar]
me gustaría saber si hay es una manera de construir la subconsulta sin usar SQL, y sin usar combinaciones.

¿Hay alguna solución?

y gracias de antemano.

Respuesta

10

Primeros dobletes Buscar por campos 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'; 

Obtener la subconsulta:

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

Añadir la condición subconsulta:

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

Modo de empleo:

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

O:

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

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

6

No, no hay una manera de construir programáticamente una subconsulta usando Yii's CDbCriteria y CActiveRecord. No parece que el Query Builder tiene una forma, tampoco.

Todavía se puede hacer SUBCONSULTAS algunas maneras diferentes, sin embargo:

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

Usted también puede realizar una unión (que probablemente será más rápido, las consultas pueden ser lento):

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

también se puede hacer una consulta SQL directo con findAllBySql:

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

puede, sin embargo, en le ast proporcionar una interfaz agradable estilo de AR a éstos, así:

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

Llamado así:

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

Una idea interesante alternativa sería la creación de su subconsulta usando el Generador de consultas CDbCommand o algo así, y luego ¿acaba de pasar la cadena de consulta SQL resultante en un CDbCritera addInCondition()? No estoy seguro si esto va a funcionar, pero puede ser que:

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

Siempre se puede extender la clase CDbCriteria base para procesar y construir subconsultas alguna manera también. ¡Podría hacer una buena extensión que podría lanzar! :)

espero que ayude!

+0

Gracias thaddeusmt, esto es sólo un ejemplo, mi consulta es aún más complicada, y es imposible hacerlo con une, y quiero hacerlo con registro activo, lo haría ¿Quiere saber si hay una forma en Yii para construir la subconsulta sin usar SQL? – Youcef04

+0

Esas son prácticamente tus opciones. Los tres devuelven los objetos de CActiveRecord, creo, por lo que técnicamente sigues usando AR. Puede usar "ámbitos" de AR para envolver las consultas y también proporcionar una buena API para sus objetos AR. Dado que aparentemente la pregunta que hiciste no es tu pregunta * real *, ¿tal vez podrías editarla? ¿O preguntar uno nuevo? Entonces, ¿es posible responderlo? – thaddeusmt

+0

la primera opción es mi solución, estaba claro que estaba buscando otra, la segunda opción usa combinaciones, eso no puede ayudarme, la tercera no es interesante. Edité la pregunta, y espero que ahora esté más claro. – Youcef04

0

Sé que esto un viejo hilo, pero tal vez alguien (como yo) todavía necesita una respuesta.

Hay un pequeño problema relacionado con las respuestas anteriores. Por lo tanto, aquí está mi mejora:

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