3、关联查询选项
之前我们提到额外的参数可以被指定在关联声明中。这些选项,指定为 name-value 对,被用来定制关联查询。它们被概述如下:
select: 为关联 AR 类查询的字段列表。默认是 '*', 意味着所有字段。查询的字段名字可用别名表达式来消除歧义(例如:COUNT(??.name) AS nameCount)。
condition: WHERE 子语句。默认为空。注意, 列要使用别名引用(例如:??.id=10)。
params: 被绑定到 SQL 语句的参数. 应当为一个由 name-value 对组成的数组()。
on: ON 子语句. 这里指定的条件将使用 and 操作符被追加到连接条件中。此选项中的字段名应被消除歧义。此选项不适用于 MANY_MANY 关联。
order: ORDER BY 子语句。默认为空。注意, 列要使用别名引用(例如:??.age DESC)。
with: 应当和此对象一同载入的子关联对象列表. 注意, 不恰当的使用可能会形成一个无穷的关联循环。
joinType: 此关联的连接类型。默认是 LEFT OUTER JOIN。
aliasToken:列前缀占位符。默认是“??.”。
alias: 关联的数据表的别名。默认是 null, 意味着表的别名和关联的名字相同。
together: 是否关联的数据表被强制与主表和其他表连接。此选项只对于HAS_MANY 和 MANY_MANY 关联有意义。若此选项被设置为 false, ......(此处原文出错!).默认为空。此选项中的字段名以被消除歧义。
having: HAVING 子语句。默认是空。注意, 列要使用别名引用。
index: 返回的数组索引类型。确定返回的数组是关键字索引数组还是数字索引数组。不设置此选项, 将使用数字索引数组。此选项只对于HAS_MANY 和 MANY_MANY 有意义
此外, 下面的选项在延迟加载中对特定关联是可用的:
group: GROUP BY子句。默认为空。注意, 列要使用别名引用(例如:??.age)。 本选项仅应用于HAS_MANY 和 MANY_MANY 关联。
having: HAVING子句。默认为空。注意, 列要使用别名引用(例如:??.age)。本选项仅应用于HAS_MANY 和 MANY_MANY 关联。
limit: 限制查询的行数。本选项不能用于BELONGS_TO关联。
offset: 偏移。本选项不能用于BELONGS_TO关联。
下面我们改变在 User 中的 posts 关联声明,通过使用上面的一些选项:
class User extends CActiveRecord

{
    public function relations()
    {
        return array(

            'posts'=>array(self::HAS_MANY, 'Post', 'author_id',
                            'order'=>'posts.create_time DESC',
                            'with'=>'categories'),
            'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'),
        );
    }
}
现在若我们访问 $author->posts, 我们将得到用户的根据发表时间降序排列的 posts. 每个 post 实例也载入了它的分类。
4、为字段名消除歧义
当一个字段的名字出现在被连接在一起的两个或更多表中,需要消除歧义(disambiguated)。可以通过使用表的别名作为字段名的前缀实现。
在关联AR查询中,主表的别名确定为 t,而一个关联表的别名和相应的关联的名字相同(默认情况下)。 例如,在下面的语句中,Post 的别名是 t ,而 Comment 的别名是 comments:
$posts=Post::model()->with('comments')->findAll();
现在假设 Post 和 Comment 都有一个字段 create_time , 我们希望取出 posts 及它们的 comments ,排序方式是先根据 posts 的创建时间,然后根据 comment 的创建时间。 我们需要消除create_time 字段的歧义,如下:
$posts=Post::model()->with('comments')->findAll(array(

    'order'=>'t.create_time, comments.create_time'
));
默认情况下,Yii 自动为每个关联表产生一个表别名,我们必须使用此前缀 ??. 来指向这个自动产生的别名。 主表的别名是表自身的名字。
5、动态关联查询选项
我们使用 with()和 with 均可使用动态关联查询选项。 动态选项将覆盖在 relations() 方法中指定的
已存在的选项。例如,使用上面的 User 模型, 若我们想要使用急切加载方法以升序来取出属于一个作者的 posts(关联中的order 选项指定为降序), 我们可以这样做:
User::model()->with(array(
    'posts'=>array('order'=>'posts.create_time ASC'),
    'profile',
))->findAll();
动态查询选项也可以在使用延迟加载方法时使用以执行关联查询。 要这样做,我们应当调用一个方法,它的名字和关联的名字相同,并传递动态查询选项 作为此方法的参数。例如,下面的代码返回一个用户的 status 为 1 的 posts :
$user=User::model()->findByPk(1);
$posts=$user->posts(array('condition'=>'status=1'));
6、关联查询的性能
如上所述,急切加载方法主要用于当我们需要访问许多关联对象时。 通过连接所有所需的表它产生一个大而复杂的 SQL 语句。一个大的 SQL 语句在许多情况下是首选的。然而在一些情况下它并不高效。
考虑一个例子,若我们需要找出最新的文章以及它们的评论。 假设每个文章有 10 条评论,使用一个大的 SQL  语句,我们将取回很多多余的 post 数据, 因为每个post 将被它的每条评论反复使用。现在让我们尝试另外的方法:我们首先查询最新的文章, 然后查询它们的评论。用新的方法,我们需要执行执行两条 SQL 语句。有点是在查询结果中没有多余的数据。
因此哪种方法更加高效?没有绝对的答案。执行一条大的 SQL 语句也许更加高效,因为它需要更少的花销来解析和执行 SQL 语句。另一方面,使用单条 SQL 语句,我们得到更多冗余的数据,因此需要更多时间来阅读和处理它们。 因为这个原因,Yii 提供了 together 查询选项一边我们在需要时选择两种方法之一。默认下, Yii 使用第一种方式,即产生一个单独的 SQL 语句来执行急切加载。我们可以在关联声明中设置 together 选项为 false 以便一些表被连接在单独的 SQL 语句中。例如,为了使用第二种方法来查询最新的文章及它们的评论,我们可以在 Post 类中声明 comments 关联如下,
public function relations()
{
    return array(

        'comments' => array(self::HAS_MANY, 'Comment', 'post_id', 'together'=>false),
    );

}
当我们执行急切加载时,我们也可以动态地设置此选项:
$posts = Post::model()->with(array('comments'=>array('together'=>false)))->findAll();