Activerecord 如何使用Yii 1.1在FROM子句中执行子查询?

Activerecord 如何使用Yii 1.1在FROM子句中执行子查询?,activerecord,yii,yii1.x,Activerecord,Yii,Yii1.x,我有一个由Yii生成的相当大和复杂的查询。为了生成这个查询,我们使用CDbCritera::with来急切地加载多个相关模型,并使用多个作用域来限制返回的记录。生成的查询大约有700行长,但看起来像这样: SELECT `t`.`column1` as `t0_c0`, `t`.`column2` as `t0_c1`, `related1`.`column1` as `t1_c0`, ... `related9`.`column5` as

我有一个由Yii生成的相当大和复杂的查询。为了生成这个查询,我们使用CDbCritera::with来急切地加载多个相关模型,并使用多个作用域来限制返回的记录。生成的查询大约有700行长,但看起来像这样:

SELECT `t`.`column1` as `t0_c0`,
       `t`.`column2` as `t0_c1`,
       `related1`.`column1` as `t1_c0`,
       ...
       `related9`.`column5` as `t9_c4`
FROM `model` `t`
    LEFT OUTER JOIN `other_model` `related1`
                 ON ( `t`.`other_model_id` = `related1`.`id` )
    ...
    LEFT OUTER JOIN `more_models` `related9`
                 ON ( `t`.`more_models_id` = `related9`.`id` )
WHERE
    ...big long WHERE clause using all of related1 - related9 to filter model...
LIMIT 10
我们的数据库有大量的数据,但也不是淫秽的。在本例中,模型表大约有126000行,每个相关模型都是一个“属于”关系,并且在t.XXX\u id上有一个索引,因此连接相当简单。问题在于WHERE子句的复杂性,它拥有多个COALESCE和IF以及CASE子句。在我们的126000行上执行过滤器需要2.6秒——远远超过我们对API端点的期望

WHERE子句分为多个不同的部分,如下所示:

WHERE
    ( ... part 1 ... )
    AND
    ( ... part 2 ... )
    AND
    ( ... part 3 ... )
每个部分对应一个范围,每个部分使用一个或多个相关模型

其中一个作用域只对单个相关模型进行筛选,这样可以将表从126000行筛选到大约2000行。我在MySQL Workbench中实验性地发现,通过简单地执行以下操作,我可以将查询时间从2.6秒缩短到0.2秒:

SELECT `t`.`column1` as `t0_c0`,
       `t`.`column2` as `t0_c1`,
       `related1`.`column1` as `t1_c0`,
       ...
       `related9`.`column5` as `t9_c4`
FROM
    (
        SELECT `model`.*
        FROM `model`
        LEFT OUTER JOIN `other_model`
                     ON ( `t`.`other_model_id` = `other_model`.`id` )
        WHERE
            ( ... part 1 ... )
    ) `t`
    LEFT OUTER JOIN `other_model` `related1`
                 ON ( `t`.`other_model_id` = `related1`.`id` )
    ...
    LEFT OUTER JOIN `more_models` `related9`
                 ON ( `t`.`more_models_id` = `related9`.`id` )
WHERE
    ( ... part 2 ... )
    AND
    ( ... part 3 ... )
LIMIT 10
通过这种方式,我们没有对原始模型表的所有126000行执行非常复杂的WHERE子句,而是对这些126000行执行更简单且索引增强的WHERE子句,然后仅对2000个相关行执行复杂的WHERE子句。这两个查询的结果相同,但在FROM子句中使用子查询会使其运行速度加快13倍

问题是,我不知道用Yii怎么做。我知道我可以使用CDbCommand构建查询,甚至可以传入原始SQL,但我得到的是一个行数组——Yii无法理解它们,也无法正确转换为正确的模型

Yii的ActiveRecord系统是否有一种类似以下内容的说法

$criteria = new CDbCriteria;
$criteria->scopes = array("part1");
$subQuery = Model::model()->buildQuery($criteria);

$criteria = new CDbCriteria;
$criteria->scopes = array("part2", "part3");
$fullQuery = $subQuery->findAll($criteria);

虽然不是一个完美的解决方案,但我确实找到了几乎同样好的解决方案。将原始查询分为两部分:

获取要在FROM子查询中选择的ID或模型 将WHERE追加到id为in的外部查询。。。 如果有人感兴趣,我会寻找我为此编写的代码,并将其作为一个示例发布在答案中,但到目前为止,这个问题几乎没有得到关注,一旦我找到了一个伪体面的解决方案,我就继续前进