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

问题描述 投票:0回答:4

API 文档中指定

  • $joinWith
    - 此查询应与 joined
  • 的关系列表
  • $with
    - 此查询应与执行的关系列表
这些ActiveQuery属性有什么区别,什么情况下应该使用

$joinWith

$with

php yii yii2
4个回答
40
投票

joinWith

 使用 
JOIN
 将关系包含在原始查询中,而 
with
 则不包含。

为了进一步说明,请考虑具有关系

Post

 的类 
comments
,如下所示:

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

时,您可以按关系排序/过滤/分组。您可能需要自己消除列名称的歧义。

参考:

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


31
投票

with
joinWith
之间的区别

使用

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() 来实现此目标。

这意味着,你现在可以自己处理

joins

innerJoins
outerJoins
 以及 Yii2 中所有相关的好东西了。 
Yii(不是 Yii2)仅使用 join
 而不是让用户决定连接类型
。关于“Join”的详细信息 -> 它是基于 SQL 的东西。您可以在这里阅读相关内容
http://en.wikipedia.org/wiki/Join_(SQL)


2
投票
请注意,除了上面帮助我弄清楚如何使用

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]);


0
投票
Yii2代码:

$query = MiniAppRisk::find()->joinWith(['country','text','riskType'])->orderBy(['risk_publish_date' => SORT_DESC]); $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => [ 'pageSize' => 10, 'page' =>1 ], ]);

结果
sql1
:

SELECT `fmm_text_risk_t`.risk_id FROM `fmm_text_risk_t` 
LEFT JOIN `fmm_text_risk_target_t` ON `fmm_text_risk_t`.`risk_id` = `fmm_text_risk_target_t`.`risk_id` 
LEFT JOIN `country` ON `fmm_text_risk_target_t`.`country_id` = `country`.`id` 
LEFT JOIN `fmm_text_t` ON `fmm_text_risk_t`.`text_id` = `fmm_text_t`.`text_id` 
LEFT JOIN `fmm_text_risk_type_relation_t` ON `fmm_text_risk_t`.`risk_id` = `fmm_text_risk_type_relation_t`.`risk_id` 
ORDER BY `risk_publish_date` DESC LIMIT 10

Yii2代码:

$query = MiniAppRisk::find()->with(['country','text','riskType'])->orderBy(['risk_publish_date' => SORT_DESC]); $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => [ 'pageSize' => 10, 'page' =>1 ], ]);

结果
sql2

SELECT DISTINCT * FROM `fmm_text_risk_t` ORDER BY `risk_publish_date` DESC LIMIT 10 ;
SELECT * FROM `fmm_text_risk_target_t` WHERE `risk_id` IN (5563, 5562, 5561, 5560, 5559, 5558, 5557, 5556, 5555, 5554);
SELECT * FROM `country` WHERE `id` IN (7, 165, 1, 20);
SELECT * FROM `fmm_text_t` WHERE `text_id` IN (15272, 15271, 15270, 15269, 15268, 15267, 15266, 15265, 15264, 15263);
SELECT * FROM `fmm_text_risk_type_relation_t` WHERE `risk_id` IN (5563, 5562, 5561, 5560, 5559, 5558, 5557, 5556, 5555, 5554);
...more 

看来joinWith生成的SQL更少,效率更高。但是,使用 joinWith 进行分页时要小心。当你检查它们的执行结果时,你会发现每页的条目数少于 10 个。
27680
27680
27900
27900
27900
30099
30099
30301
30301
30489


© www.soinside.com 2019 - 2024. All rights reserved.