web-dev-qa-db-ja.com

Yii2の$ withと$ joinWithの違いとそれらを使用するタイミングは何ですか?

APIドキュメントでは、

  • $joinWith-このクエリが持つべきリレーションのリストjoined with
  • $with-このクエリが持つべきリレーションのリスト実行

これらのActiveQueryプロパティの違いは何ですか?また、どのような状況で$joinWithおよび$with

31
NAT3863

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を使用しています。

追加情報

doc -> 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)

24
lin

joinWithJOINを使用して元のクエリにリレーションを含めますが、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を使用する場合、リレーション別にby/filter/groupを並べ替えることができます。自分で列名を明確にする必要がある場合があります。

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

35
topher

上記の素晴らしい回答に加えて、joinWith()の使用方法を理解するのに役立ちました。また、joinWith()を使用したいときに、曖昧な列名がある場合は、Yii/ActiveRecordは、通常期待するもの(左端のテーブル)ではなく、自動的にランダムな列を選択するようです。何かを指定することにより、SELECT句で左端のテーブルを指定するのが最善です$query->select("post.*")のように、いくつかの内部テーブルからidを取得していましたが、それらを理解するまで、左端のテーブルからwereのように使用されていました。

もう1つの注意点は、can joinwith関係のエイリアスを指定することです。したがって、次のように言えます。

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