2011-12-11 25 views
7

Có thể thực hiện truy vấn phụ trong ActiveRecord trong Yii không?Truy vấn phụ ActiveRecord Yii

tôi có một câu hỏi như thế này:

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

tôi hiện đang sử dụng mã fallowing:

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

[Chỉnh sửa]
tôi muốn biết nếu có là một cách để xây dựng truy vấn phụ mà không sử dụng SQL và không sử dụng các phép nối.

Có giải pháp nào không?

và cảm ơn trước.

Trả lời

10

tìm doublets đầu tiên của lĩnh vực 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'; 

Lấy subquery:

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

Thêm điều kiện subquery:

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

Làm thế nào để sử dụng:

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

Hoặc:

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

Nguồn: http://www.yiiframework.com/wiki/364/using-sub-query-for-doubletts/

6

Không, không có cách nào để lập trình cấu trúc truy vấn con bằng cách sử dụng CDbCriteriaCActiveRecord của Yii. Nó không giống như Query Builder có một cách, một trong hai.

Bạn vẫn có thể làm subqueries một vài cách khác nhau, tuy nhiên:

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

Bạn cũng có thể làm một tham gia (mà có lẽ sẽ nhanh hơn, truy vấn con có thể được làm chậm):

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

Bạn cũng có thể thực hiện truy vấn SQL trực tiếp với findAllBySql:

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

Bạn có thể, tuy nhiên, tại le ast cung cấp một giao diện phong cách AR tốt đẹp để những như vậy:

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

gọi như vậy:

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

Một ý tưởng thay thế thú vị sẽ được tạo subquery của bạn bằng cách sử dụng xe cộ và Query CDbCommand hay một cái gì đó, và sau đó chỉ cần vượt qua chuỗi truy vấn SQL kết quả vào một CDbCritera addInCondition()? Bạn không chắc chắn nếu điều này sẽ làm việc, nhưng nó có thể:

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

Bạn luôn có thể mở rộng các lớp CDbCriteria cơ sở để xử lý và xây dựng các truy vấn con bằng cách nào đó là tốt. Có thể làm cho một phần mở rộng tốt đẹp, bạn có thể phát hành! :)

Tôi hy vọng điều đó sẽ hữu ích!

+0

Cảm ơn thaddeusmt, đây là một ví dụ duy nhất, truy vấn của tôi thậm chí còn phức tạp hơn, và nó không thể làm điều đó với tham gia, và tôi muốn làm điều đó bằng kỷ lục hoạt động, tôi sẽ muốn biết nếu có một cách trong Yii để xây dựng các truy vấn phụ mà không sử dụng SQL? – Youcef04

+0

Đó là khá nhiều lựa chọn của bạn. Tất cả ba đối tượng CActiveRecord trả về, tôi tin rằng, vì vậy bạn vẫn đang sử dụng AR. Bạn có thể sử dụng AR "phạm vi" để bọc các truy vấn và cung cấp một API tốt đẹp cho các đối tượng AR của bạn, là tốt. Vì dường như câu hỏi bạn hỏi không phải là câu hỏi * thực tế * của bạn, có lẽ bạn có thể chỉnh sửa nó? Hoặc hỏi một cái mới? Vì vậy, trả lời nó là có thể? – thaddeusmt

+0

tùy chọn đầu tiên là giải pháp của tôi, rõ ràng là tôi đang tìm kiếm giải pháp khác, tùy chọn thứ hai sử dụng kết nối, không thể giúp tôi, thứ ba không thú vị. tôi đã chỉnh sửa câu hỏi, và tôi hy vọng nó rõ ràng hơn bây giờ? – Youcef04

0

Tôi biết điều này là một chủ đề cũ nhưng có lẽ ai đó (như tôi) vẫn cần một câu trả lời.

Có một số vấn đề nhỏ liên quan đến câu trả lời trước đó. Vì vậy, đây là nâng cao của tôi:

$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); 
Các vấn đề liên quan