2016-02-19 21 views
0

我正在使用基於我的表格的Gridview(我打電話給TABLE0),我也有一個搜索表單。這裏是我的表的樣本和與之相關的其他表:來自JoinWith()的SQL與主ActiveQuery分離,使OnCondition()拋出未知的列錯誤

TABLE0

ID | TALBE1_ID | (more fields) 

TABLE1

ID | TABLE2_ID | TABLE3_ID | (more fields) 

TABLE2表3

ID | (more fields) 

正如我們所見,TABLE1TABLE2TABLE3都有關係。

我目前的問題是當我嘗試使我的搜索表單。根據TABLE1(在這種情況下,FIELDCHECK)中的字段,我將使用其中一個搜索參數(在此例中爲customAttribute)從TABLE2TABLE3(並且該列不具有相同名稱)搜索特定列。

這裏是我當前的搜索(不工作):

public customAttribute; 
// more attributes, but not using at the moment 

public function search($params) 
{ 
    $query = self::find()->orderBy(['TABLE0.FIELD0' => SORT_ASC]); 

    $dataProvider = new ActiveDataProvider([ 
     'query' => $query 
    ]); 

    $this->load($params); 

    if (!$this->validate()) { 
     $query->where('0=1'); 
     return $dataProvider; 
    } 

    $query->joinWith([ 
     'relationTable1' => function ($query1) { 
      $query1->andFilterWhere(['in', 'TABLE1.FIELDCHECK', ['0','1','2','3']]) 
      // more ->andFilterWhere([]) but i'm not using at the moment 
      ->joinWith([ 
        'relationTable2' => function ($query2) { 
         $query2->onCondition(['TABLE1.FIELDCHECK' => '0']) // if FIELDCHECK is 0 i will do this join. 
          ->andFilterWhere(['TABLE2.FIELD2' => $this->customAttribute]); 
        } 
       ]) 
       ->joinWith([ 
        'relationWithTable3' => function ($query3) { 
         $query3->onCondition(['<>', 'TABLE1.FIELDCHECK', '0']) // if FIELDCHECK is not 0 i will do this join instead 
          ->andFilterWhere(['TABLE3.FIELD3' => $this->customAttribute]); 
        } 
       ]); 
     } 
    ]); 

    return $dataProvider; 
} 

這是拋出一個SQL錯誤:

General error: 4104 General SQL Server error: Check messages from the SQL Server [4104] (severity 16) [(null)] 
The SQL being executed was: SELECT * FROM [TABLE2] WHERE ([ID] IN ('163203002', '163202002', '163203001', '163203004', '163203003', '163202001', '163202003', '163202004', '161201005', '161201012', '161201020', '161201021', '161201022', '161201023', '161201034', '161201042', '161201043', '161201046', '161201701', '161201047')) AND ([TABLE1].[FIELDCHECK]='0') 

好了,有了這個錯誤,我可以看到joinWith SQL是運行分離從主查詢(在獲得ID之後)。但是,如果我試圖讓這個$query$query->createCommand()->sql生成的SQL我得到:

SELECT [TABLE0].* FROM [TABLE0] 
LEFT JOIN [TABLE1] ON [TABLE0].[TABLE1_ID] = [TABLE1].[ID] 
LEFT JOIN [TABLE2] ON ([TABLE1].[TABLE2_ID] = [TABLE2].[ID]) AND ([TABLE1].[FIELDCHECK] = '0') 
LEFT JOIN [TABLE3] ON ([TABLE1].[TABLE3_ID] = [TABLE2].[ID]) AND ([TABLE1].[FIELDCHECK] <> '0') 
WHERE [TABLE1].[FIELDCHECK] IN ('0','1','2','3') ORDER BY [TABLE0].[FIELD0]; 

並運行此查詢,它工作正常。我知道我可以嘗試在這個Gridview中使用原始的sql(可能與ArrayDataProvider,但我仍然不知道如何),但我真的想使這個ActiveDataProvider工作。

我刪除了所有不相關的代碼,但我在代碼中留了言。

回答

0

好的,我找到了一個解決方案。

因此,這裏的主要問題是,當我使用joinWith()時,我無法在我的onCondition()方法中調用連接表之外的任何表。我想通了,與其做這種查詢(OBS:註釋代碼是andFilterWhere()條件):

SELECT [TABLE0].* FROM [TABLE0] 
LEFT JOIN [TABLE1] ON [TABLE0].[TABLE1_ID] = [TABLE1].[ID] 
LEFT JOIN [TABLE2] ON ([TABLE1].[TABLE2_ID] = [TABLE2].[ID]) AND ([TABLE1].[FIELDCHECK] = '0') // AND ([TABLE2.FIELD2] = $this->customAttribute) 
LEFT JOIN [TABLE3] ON ([TABLE1].[TABLE3_ID] = [TABLE3].[ID]) AND ([TABLE1].[FIELDCHECK] <> '0') // AND ([TABLE3.FIELD3] = $this->customAttribute) 
WHERE [TABLE1].[FIELDCHECK] IN ('0','1','2','3') ORDER BY [TABLE0].[FIELD0]; 

我能做到這一點查詢,而不是:

SELECT [TABLE0].* FROM [TABLE0] 
LEFT JOIN [TABLE1] ON [TABLE0].[TABLE1_ID] = [TABLE1].[ID] 
LEFT JOIN [TABLE2] ON [TABLE1].[TABLE2_ID] = [TABLE2].[ID] 
LEFT JOIN [TABLE2] ON [TABLE1].[TABLE3_ID] = [TABLE3].[ID] 
WHERE (
    (([TABLE1].[FIELDCHECK] = '0') /* AND ([TABLE2].[FIELD2] = $this->customAttribute) */) 
    OR 
    (([TABLE1].[FIELDCHECK] <> '0') /* AND ([TABLE3].[FIELD3] = $this->customAttribute) */) 
) 
AND ([TABLE1].[FIELDCHECK] IN ('0','1','2','3')) 
ORDER BY [TABLE0].[FIELD0] 

下面是最終搜索

public customAttribute; 
// more attributes, but not using at the moment 

public function search($params) 
{ 
    $query = self::find()->orderBy(['TABLE0.FIELD0' => SORT_ASC]); 

    $dataProvider = new ActiveDataProvider([ 
     'query' => $query 
    ]); 

    $this->load($params); 

    if (!$this->validate()) { 
     $query->where('0=1'); 
     return $dataProvider; 
    } 

    $query->joinWith([ 
     'relationTable1' => function ($query1) { 
      $query1->andFilterWhere(['in', 'TABLE1.FIELDCHECK', ['0','1','2','3']]) 
      // more ->andFilterWhere([]) but i'm not using at the moment 
      ->joinWith(['relationTable2', 'relationWithTable3']); 
     } 
    ]); 

    $query->andFilterwhere([ 
     'or', 
     ['and', ['TABLE1.FIELDCHECK' => '0'], ['like', 'TABLE2.FIELD2', $this->customAttribute]], 
     ['and', ['<>', 'TABLE1.FIELDCHECK', '0'], ['like', 'TABLE3.FIELD3', $this->customAttribute]] 
    ]); 

    return $dataProvider; 
}