Yii2 中的 $with 和 $joinWith 有啥区别以及何时使用它们?

Posted

技术标签:

【中文标题】Yii2 中的 $with 和 $joinWith 有啥区别以及何时使用它们?【英文标题】:What is the difference between $with and $joinWith in Yii2 and when to use them?Yii2 中的 $with 和 $joinWith 有什么区别以及何时使用它们? 【发布时间】:2014-10-25 08:10:53 【问题描述】:

在 API 文档中指定

$joinWith - 此查询应加入与的关系列表 $with - 此查询应该执行的关系列表

这些ActiveQuery属性有什么区别,在什么情况下应该使用$joinWith$with

【问题讨论】:

【参考方案1】:

请注意,除了上述帮助我弄清楚如何使用 joinWith() 的精彩答案之外,每当您想使用 joinWith() 并且列名不明确时,Yii / ActiveRecord 似乎会自动选择一个随机列,而不是您通常期望的(最左边的表格)。最好在SELECT 子句中指定最左边的表,例如指定$query->select("post.*")。我从一些内部表中获取 id,并且它们被使用,就像它们 来自最左边的表一样,直到我弄清楚这一点。

另一点需要注意的是,您可以为 joinwith 关系指定一个别名,因此您可以这样说:

$post->find()
->joinWith(["user u"])
->where(["u.id"=>$requestedUser->id])
->select("post.*")
->orderBy(["u.created_at"=>SORT_DESC]);

【讨论】:

【参考方案2】:

joinWith 使用 JOIN 将关系包含在原始查询中,而 with 没有。

为了进一步说明,请考虑具有关系 comments 的类 Post,如下所示:

class Post extends \yii\db\ActiveRecord 
    ...
    public function getComments() 
        return $this->hasMany(Comment::className(), ['post_id' => 'id']);
    

使用with下面的代码:

$post = Post::find()->with('comments');

导致以下 sql 查询:

SELECT `post`.* FROM `post`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...)

而下面的joinWith 代码:

$post = Post::find()->joinWith('comments', true)

查询结果:

SELECT `post`.* FROM post LEFT JOIN `comment` comments ON post.`id` = comments.`post_id`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...);

因此,当使用joinWith 时,您可以按关系排序 by/filter/group。您可能必须自己消除列名的歧义。

参考:http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#lazy-eager-loading

【讨论】:

【参考方案3】:

withjoinWith 之间的区别

使用 with 方法会产生以下 SQL 查询

$users = User::find()->with('userGroup');

SELECT * FROM `user`;
SELECT * FROM `userGroup` WHERE userId = ...

...在使用joinWith时会产生这个SQL查询

$users = User::find()->joinWith('userGroup', true)

SELECT * FROM user LEFT JOIN `userGroup` userGroup ON user.`id` = userGroup.`userId`;

所以当我需要过滤或搜索相关表中的数据时,我会使用joinWith

附加信息

docu -> http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations 会告诉你:

"在使用关系数据库时,一个常见的任务是连接多个表并将各种查询条件和参数应用于 JOIN SQL 语句。而不是显式调用 yii\db\ActiveQuery::join() 来构建在 JOIN 查询中,你可以重用现有的关系定义并调用 yii\db\ActiveQuery::joinWith() 来实现这个目标。"

也就是说,你现在可以自己处理 joinsinnerJoinsouterJoins 以及 Yii2 中所有相关的好东西。 Yii(不是 Yii2)只使用join 而不是让用户决定加入的类型。关于“加入”的详细信息->它是基于 SQL 的东西。你可以在这里阅读http://en.wikipedia.org/wiki/Join_(SQL)

【讨论】:

joinWith 仍然会导致 2 个查询...原因我不太明白...我一直理解“SQL 查询越少越好”。因此,joinWith 只有在查询相关表中的列时才有用,否则只是一个缺点。 SQL 查询越少越好,这并不一定是真的。这取决于索引列的好坏。 withjoinWith 之间的最大区别将在巨大的数据集上显着 - 例如在两个表之间连接数百万条记录比在索引列上进行简单的子查询(实际上是两个简单的查询)更加密集的操作。因此,在这种情况下使用更简单的with 很可能是更好的选择。 @TheStoryCoder 尝试将 eagerLoading 设置为 false。这必须使它只执行一个查询而不是两个。

以上是关于Yii2 中的 $with 和 $joinWith 有啥区别以及何时使用它们?的主要内容,如果未能解决你的问题,请参考以下文章

Yii2中多表关联查询(joinjoinwith) with是不执行sql的

yii2 一对多关系的对分页造成的影响

YII with()

yii2_关联表

Yii2.如何在 MongoDB/ActiveQuery 中使用查找?

yii2 gridview没有使用hasMany关系显示所有左连接值