JoinWith()中的SQL与主ActiveQuery分离,使OnCondition()抛出未知的列错误

时间:2016-02-19 20:32:18

标签: php sql yii2

我使用基于我的表格的Gridview(我打电话给TABLE0),我也有一个搜索表单。以下是我的表格示例以及与之相关的其他表格:

TABLE0

ID | TALBE1_ID | (more fields)

TABLE1

ID | TABLE2_ID | TABLE3_ID | (more fields)

TABLE2 TABLE3

ID | (more fields)

我们可以看到,TABLE1TABLE2TABLE3都有关联。

我目前的问题是当我尝试制作我的搜索表单时。根据{{​​1}}的字段(在本例中为TABLE1),我将使用其中一个搜索参数(在本例中为FIELDCHECK)来搜索customAttribute中的特定列}或TABLE2(并且该列的名称不同)。

这是我目前的搜索(不工作):

TABLE3

这是抛出一个SQL错误:

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

好的,有了这个错误,我可以看到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') sql正在运行,与主查询分开(在获取id之后)。但是,如果我尝试使用joinWith获取此$query生成的sql,我得到了:

$query->createCommand()->sql

运行此查询,它运行正常。我知道我可以尝试在这个Gridview中使用原始的sql(可能与ArrayDataProvider,但我仍然不确定如何),但我真的想让这个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]; 工作。

我在这里删除了所有不相关的代码,但我在代码中进行了评论。

1 个答案:

答案 0 :(得分: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;
}