2011-12-11 68 views
7

是否有可能在Yii中的ActiveRecord中進行子查詢?子查詢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構建子查詢的方式,也不使用連接。

有沒有解決方法?

並提前致謝。

回答

10

先找到雙峯的數據庫字段:

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

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

你也可以做一個直接的SQL查詢與findAllBySql

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

你可以,但是,在勒AST提供了一個很好的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; 

一個有趣的替代想法是使用Query Builder的CDbCommand或東西來創建子查詢,然後只需將生成的SQL查詢字符串傳遞給CDbCritera addInCondition()?不知道這是否會工作,但它可能:

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

您可以隨時擴展基CDbCriteria類處理,並建立子查詢以某種方式爲好。可能會發佈一個很好的擴展! :)

我希望有幫助!

+0

感謝thaddeusmt,這僅是一個例子,我的查詢更爲複雜,這是不可能加入做到這一點,我想這樣做,使用活動記錄,我會想知道Yii中是否有方式構造不使用SQL的子查詢? – Youcef04

+0

這些都是你的選擇。我相信所有三個返回CActiveRecord對象,所以你在技術上仍然使用AR。您可以使用AR「範圍」來包裝查詢,併爲您的AR對象提供一個很好的API。由於顯然你問的問題不是你的*實際問題,也許你可以編輯它?或者問一個新的?那麼回答它是可能的? – thaddeusmt

+0

第一個選項是我的解決方案,很明顯我正在尋找另一個,第二個選項使用連接,這不能幫助我,第三個是沒有意義的。我編輯了這個問題,我希望現在更清楚一點? – Youcef04

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