2011-12-11 4 views
7

Yii에서 ActiveRecord에서 하위 쿼리를 만들 수 있습니까?하위 쿼리 ActiveRecord Yii

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

내가 현재 fallowing 코드를 사용하고 있습니다 :

내가이 같은 쿼리를

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

[편집]
내가 알고 싶은이 SQL을 사용하지 않고 조인을 사용하지 않고 하위 쿼리를 생성하는 방식입니다.

해결책이 있습니까?

그리고 미리 감사드립니다.

답변

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

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

또한 findAllBySql에 직접 SQL 쿼리를 수행 할 수 있습니다

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

한 가지 흥미로운 대안 아이디어는 다음 쿼리 빌더의 CDbCommand 또는 무언가를 사용하여 하위 쿼리를 만들기 위해, 그리고 것 결과 SQL 쿼리 문자열을 CDbCritera addInCondition()으로 전달하면됩니까? 이 작동하지만 수도 확실하지 경우 :

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

당신은 항상 처리하고 어떻게 든뿐만 아니라 하위 쿼리를 구축 할 수있는 기본 CDbCriteria 클래스를 확장 할 수 있습니다. 당신이 풀 수있는 멋진 확장 기능을 만들 수 있습니다! :)

나는 그것이 도움이 되길 바래!

+0

덕분에 내 쿼리가 훨씬 더 복잡하고, 조인 함께 할 수 없다, 그리고 내가 활동 기록을 사용하고 싶지 : 그래서, 여기 내 개선이다 SQL을 사용하지 않고 하위 쿼리를 구성하는 방법이 Yii에 있는지 알고 싶습니까? – Youcef04

+0

이것들은 당신의 선택입니다. 세 가지 모두 CActiveRecord 객체를 반환하므로 기술적으로 여전히 AR을 사용하고 있습니다. AR "스코프"를 사용하여 쿼리를 랩핑하고 AR 객체에 멋진 API를 제공 할 수 있습니다. 분명히 묻는 질문이 실제 * 질문이 아니기 때문에 아마도 편집 할 수 있습니까? 아니면 새로운 것을 물어보십시오. 그래서 대답하는 것이 가능합니까? – thaddeusmt

+0

첫 번째 옵션은 내 솔루션입니다. 분명히 다른 것을 찾고있었습니다. 두 번째 옵션은 조인을 사용하여 나에게 도움이되지 않습니다. 세 번째 옵션은 흥미롭지 않습니다. 나는 그 질문을 편집했는데, 지금은 더 명확 해 졌으면 좋겠다. – Youcef04

0

난 아직 답을 필요로 오래된 스레드하지만 (나 같은) 어쩌면 사람이 알고있다.

이전 답변과 관련된 작은 문제가 있습니다. 내가 것, 이것은 예를 들어이 아니라 thaddeusmt

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