0

私は2つのモデルを持っていUserますUserProfile. has_one useruser_profile とuser_profilebelongs_to ユーザー。

1) 選択せずに検索

コンソールでのこのクエリは正常に機能し、2 つの SQL クエリのみを使用します。

>> User.find(:all, :limit => 10, :include => [ :user_profile ])

 

User Load (0.3ms)   SELECT * FROM `users` LIMIT 10
UserProfile Load (0.3ms)   SELECT `user_profiles`.* FROM `user_profiles`
      WHERE (`user_profiles`.user_id IN (1,2,3,...)) 

2)userモデルを選択して検索

Userモデルから列を選択できます。

>> User.find(:all, :select => '`users`.id, `users`.last_name',
     :limit => 10, :include => [ :user_profile ])

 

User Load (0.3ms)   SELECT `users`.id, `users`.last_name FROM `users` LIMIT 10
UserProfile Load (0.2ms)   SELECT `user_profiles`.* FROM `user_profiles`
      WHERE (`user_profiles`.user_id IN (17510,18087,17508,17288...))

すべて正常に動作します。users.id2 番目のクエリが機能しない (NULL を返す) ため、ユーザーが選択した列を設定する必要があることに注意してください。

3)user_profileモデルを選択して検索

しかし、UserProfileモデルから列を選択しようとすると、クエリが 1 つしか得られず、処理されません。:select

>> User.find(:all,
     :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
     :limit => 10, :include => [ :user_profile ])

 

User Load Including Associations (0.6ms) SELECT `users`.`id` AS t0_r0,
  `users`.`login` AS t0_r1, ....
  `user_profiles`.`id` AS t1_r0,
  `user_profiles`.`birth_date` AS t1_r1,
  LEFT OUTER JOIN `user_profiles` ON user_profiles.user_id = users.id LIMIT 10

ご覧のとおり、Rails クエリには、ユーザーからのフィールドと、選択しなかった user_profiles からのフィールドが含まれています。

4) 参加方法

codeit はjoinfunction を持つメソッドを目的としています:

user_details = User.find(:all,
   :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
   :limit => 10, :joins => [ :user_profile ]
)

 

User Load (0.2ms) SELECT `users`.id, `users`.last_name, `user_profiles`.permalink
   FROM `users`
   INNER JOIN `user_profiles` ON user_profiles.user_id = users.id
   LIMIT 10

このソリューションは、SQL クエリでは問題なく機能しますが、ユーザーとユーザー プロファイルの間に「リンク」を作成しません。10 個の新しいクエリが必要ですが、方法 1 と 2 は 2 つの SQL クエリしか作成しません。

 user_details.map(&:user_profile).map(&:permalink)
 UserProfile Load (0.3ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 1) LIMIT 1
 UserProfile Load (0.2ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 2) LIMIT 1
 ... (10 times) ...
 UserProfile Load (0.3ms)   SELECT * FROM `user_profiles` WHERE (`user_profiles`.user_id = 10) LIMIT 1

最初の 2 つのクエリと同じ結果が得られる正しい構文はありますが、:select魔女を使用してモデルのいくつかの列のみを選択しますか?

4

1 に答える 1

0

使用join:

User.find(:all,
 :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
 :limit => 10, :joins => [ :user_profile ])

includeに使用されeager loadingます。(N+1)が大きい場合に user_profile にアクセスするためのクエリの問題を解決するために使用されusersますuser_profile。含まれているテーブルを選択する場合columnsは、 を使用する必要がありますjoinselect含まれているテーブルの列を使用すると、句から無視されます。

編集:

user_details = User.find(:all,
   :select => '`users`.id, `users`.last_name, `user_profiles`.permalink',
   :limit => 10, :joins => [ :user_profile ]
 )

user_details.map(&:permalink)
于 2013-03-18T17:25:55.127 に答える