Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sub-queries ActiveRecord Yii

Is it possible to make sub-queries in ActiveRecord in Yii?

i have a query like this:

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

i'm currently using the fallowing code:

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

[Edit]
i would like to know if there is a manner to construct the sub-query without using SQL, and without using joins.

Is there any solution ?

and thanks in advance.

like image 869
Youcef04 Avatar asked Dec 11 '11 21:12

Youcef04


People also ask

How to write SQL query in Yii2?

Call yii\db\QueryBuilder to generate a SQL statement based on the current construct of yii\db\Query; Create a yii\db\Command object with the generated SQL statement; Call a query method (e.g. queryAll()) of yii\db\Command to execute the SQL statement and retrieve the data.

Is null in Yii2 query?

Yii2 will use "IS NULL" if the $values === null , but in case the value is supplied as an array, and one of those array elements is null, it will not get any special treatment, resulting in the query never matching any records with NULL value.

What is Query Builder in Yii2?

The Yii Query Builder provides an object-oriented way of writing SQL statements. It allows developers to use class methods and properties to specify individual parts of a SQL statement.


2 Answers

First find doublets by db fields:

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

Get the subquery:

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

Add the subquery condition:

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

How to use:

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

Or:

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

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

like image 92
Slim Fadi Avatar answered Oct 01 '22 18:10

Slim Fadi


No, there is not a way to programmatically construct a subquery using Yii's CDbCriteria and CActiveRecord. It doesn't look like the Query Builder has a way, either.

You can still do subqueries a few different ways, however:

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

You can also do a join (which will probably be faster, sub-queries can be slow):

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

You can also do a direct SQL query with findAllBySql:

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

You can, however, at least provide a nice AR style interface to these like so:

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

Called like so:

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

One interesting alternative idea would be to create your subquery using the Query Builder's CDbCommand or something, and then just pass the resulting SQL query string into a CDbCritera addInCondition()? Not sure if this will work, but it might:

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

You can always extend the base CDbCriteria class to process and build subqueries somehow as well. Might make a nice extension you could release! :)

I hope that helps!

like image 32
thaddeusmt Avatar answered Oct 01 '22 18:10

thaddeusmt