2013-11-25 13 views
46

Tôi đang cố gắng làm điều gì đó mà tôi nghĩ nó sẽ đơn giản nhưng có vẻ như không.Tìm tất cả các bản ghi có số lượng liên kết lớn hơn không

Tôi có mô hình dự án có nhiều vị trí tuyển dụng.

class Project < ActiveRecord::Base 

    has_many :vacancies, :dependent => :destroy 

end 

Tôi muốn nhận tất cả các dự án có ít nhất 1 vị trí trống. tôi đã cố gắng một cái gì đó như thế này:

Project.joins(:vacancies).where('count(vacancies) > 0') 

nhưng nó nói

SQLite3::SQLException: no such column: vacancies: SELECT "projects".* FROM "projects" INNER JOIN "vacancies" ON "vacancies"."project_id" = "projects"."id" WHERE ("projects"."deleted_at" IS NULL) AND (count(vacancies) > 0).

Trả lời

29

joins sử dụng một bên tham gia theo mặc định để sử dụng Project.joins(:vacancies) di chúc có hiệu lực chỉ trả lại dự án có một vị trí tuyển dụng liên quan.

UPDATE:

Như đã chỉ ra bởi @mackskatz trong các bình luận, mà không có một khoản group, các mã trên sẽ trở lại các dự án trùng lặp cho các dự án với nhiều hơn một chỗ trống. Để xóa các mục trùng lặp, hãy sử dụng

Project.joins(:vacancies).group('projects.id') 
+0

Tuy nhiên, không áp dụng nhóm theo mệnh đề này sẽ trả về nhiều đối tượng dự án cho các dự án có nhiều hơn một vị trí trống. – mackshkatz

19

Vâng, vacancies không phải là trường trong kết nối. Tôi tin rằng bạn muốn:

Project.joins(:vacancies).group("projects.id").having("count(vacancies.id)>0") 
+0

Trường hợp đã làm: các kỳ nghỉ đến từ đâu? –

-4

Lỗi này cho bạn biết rằng vị trí tuyển dụng không phải là một cột trong dự án.

này nên làm việc

Project.joins(:vacancies).where('COUNT(vacancies.project_id) > 0') 
+4

'chức năng tổng hợp không được cho phép trong WHERE' – squixy

87

1) Để có được dự án có ít nhất 1 vị trí tuyển dụng:

Project.joins(:vacancies).group('projects.id') 

2) Để có được dự án với hơn 1 vị trí tuyển dụng:

Project.joins(:vacancies).group('projects.id').having('count(project_id) > 1') 

3) Hoặc, nếu Vacancy bộ mô hình bộ nhớ cache truy cập:

belongs_to :project, counter_cache: true 

thì đây sẽ làm việc, quá:

Project.where('vacancies_count > ?', 1) 

quy tắc uốn cho vacancy có thể cần phải specified manually?

2
# None 
Project.joins(:vacancies).group('projects.id').having('count(vacancies) = 0') 
# Any 
Project.joins(:vacancies).group('projects.id').having('count(vacancies) > 0') 
# One 
Project.joins(:vacancies).group('projects.id').having('count(vacancies) = 1') 
# More than 1 
Project.joins(:vacancies).group('projects.id').having('count(vacancies) > 1') 
0

Nếu không có nhiều Rails ma thuật, bạn có thể làm:

Project.where('(SELECT COUNT(*) FROM vacancies WHERE vacancies.project_id = projects.id) > 0') 

Đây là loại điều kiện này sẽ làm việc trong tất cả các phiên bản Rails càng nhiều công việc được thực hiện trực tiếp ở phía bên DB. Thêm vào đó, chaining phương thức .count cũng sẽ hoạt động tốt. Tôi đã bị đốt cháy bởi các truy vấn như Project.joins(:vacancies) trước đây. Tất nhiên, có những ưu và khuyết điểm vì nó không phải là DB bất khả tri.

+0

Điều này là chậm hơn nhiều so với tham gia và nhóm phương pháp, như 'lựa chọn đếm (*) ..' subquery sẽ thực hiện cho mỗi dự án. – YasirAzgar

Các vấn đề liên quan