2011-02-09 29 views
11

Vì vậy, tôi có Bài đăng và Người dùng.
Đăng has_many người dùng và người dùng thuộc về một bài đăng.
Tôi cần một phát hiện rằng sẽ tìm thấy tất cả các bài viết mà không có bất kỳ người sử dụng như sau:tìm tất cả số không có trong hiệp hội

Post.first.users 
=> [] 

Trả lời

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

Nếu truy vấn phụ chứa một số không, thì không có gì sẽ được trả về và bạn có thể muốn sử dụng 'NOT EXISTS' thay vào đó, như tôi cần trong trường hợp cụ thể của tôi. [Đọc thêm] (http://stackoverflow.com/questions/173041/not-in-vs-not-exists). – manafire

1

Post.first.users.empty? nên là đủ nếu người sử dụng trả về một mảng.

Nếu bạn muốn kiểm tra cho mỗi bài bạn có thể làm

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

tôi cần phải tìm tất cả các bài viết ... không chỉ là – Trace

+0

đầu tiên vì vậy tôi cần một cái gì đó giống như Post.all (: include =>: users,: conditions => "users =?", nil) – Trace

+0

'Post.each do | p | Nếu p.users == không làm bất kỳ kết thúc nào' – acconrad

2

Nếu bạn cần một cái gì đó mà là nhanh chóng, sử dụng một câu lệnh SQL như:

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

tôi đoán một sql với trong có thể gây ra vấn đề hiệu suất nếu bảng cơ sở dữ liệu có nhiều hàng. cẩn thận với điều đó

+2

Phải. Bắt đầu với mã dễ đọc nhất, bảo mật nó bằng các thử nghiệm và sau đó bạn có thể bắt đầu tối ưu hóa hiệu suất. Nếu không có kiểm tra, bạn có nguy cơ rằng bạn "tối ưu hóa" một số hồ sơ do tai nạn. Và luôn đo lường hiệu suất thực tế: phiên bản được tối ưu hóa không phải lúc nào cũng nhanh nhất. – Arsen7

2

một cái gì đó như thế:

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

Tôi biết điều này được gắn thẻ như Rails 3, nhưng nếu bạn đang sử dụng Rails 4, tôi đã làm nó như thế này.

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

học kinh nghiệm này chỉ ngày hôm nay:

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

trình với Rails 4+ ít nhất.

Cập nhật:

Trong Rails 5+, bạn có thể sử dụng thay vì left_joins:

Post.left_joins(:users).merge(User.where(id: nil)) 
Các vấn đề liên quan