2011-02-09 6 views
11

私は投稿とユーザーを持っています。
投稿は投稿数が多く、ユーザーは投稿に所属しています。
私は次のような任意のユーザーを持っていけない、すべての記事を検索します検索を必要とする:ユーザーが配列を返す場合アソシエーション内にあるすべてが見つからない

Post.first.users 
=> [] 

答えて

26
Post.where("id not in (select post_id from users)") 
+0

サブクエリにはnilが含まれていれば、何も返されず、私の場合に必要だったように、' NOT EXISTS'を代わりに使いたいかもしれません。 [さらに読む](http://stackoverflow.com/questions/173041/not-in-vs-not-exists)。 – manafire

1

Post.first.users.empty?は十分なはずです。

SELECT * 
FROM posts p 
LEFT OUTER JOIN users u ON p.id = u.post_id 
WHERE u.id IS null 
+0

を私はちょうど最初 – Trace

+0

...すべての記事を検索する必要はありませんので、私はPost.allようなものが必要(:include =>:users、:conditions => "users =?"、nil) – Trace

+0

'Post.each do | p |もしp.users == nilなら何でも終了する ' – acconrad

2

は、のようなSQL文を採用して行うことができますinを使用すると、データベース表に多数の行がある場合にパフォーマンスの問題が発生する可能性があります。そのようなこと

1

は、私はSQLを推測:あなたは、各ポストをチェックしたい場合は

あなたは高速で何かが必要な場合

Post.each do |p| 
    if p.users.empty? 
    do whatever 
    end 
end 
+2

右。最も読みやすいコードから始め、テストでそのコードを保護してから、パフォーマンスを最適化することができます。テストがなければ、偶然にいくつかのレコードを「最適化」するリスクがあります。そして、常に実際のパフォーマンスを測定してください:最適化されたバージョンが常に最速であるとは限りません。 – Arsen7

2

何かに注意してください:

p = Post.arel_table 
u = User.arel_table 

posts = Post.find_by_sql(p.join(u).on(p[:user_id].eq(u[:p_id])).where(u[:id].eq(nil)).to_sql) 
1

私は、これはRailsの3としてタグ付けされて知っていますが、Railsの4を使用している場合、私はこのようにそれを行ってきました。レールと

Post.eager_load(:users).merge(User.where(id: nil)) 

作品4+少なくとも:

Post.where.not(user_id: User.pluck(:id)) 
14

はこのちょうど今日のことを学びました。

更新:

Railsの5+では、あなたの代わりにleft_joinsを使用することができます。

Post.left_joins(:users).merge(User.where(id: nil)) 
関連する問題