2012-03-18 29 views
14

Tôi có câu hỏi sau đây:Rails 3, ActiveRecord, PostgreSQL - ".uniq" lệnh không hoạt động?

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15).uniq 

và mang lại cho tôi những lỗi

PG::Error: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list 
LINE 1: ...s"."user_id" WHERE (articles.user_id != 1) ORDER BY Random() L... 

Khi tôi cập nhật các truy vấn ban đầu để

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15)#.uniq 

nên lỗi đã biến mất ... Trong MySQL .uniq hoạt động, trong PostgreSQL thì không. Tồn tại bất kỳ thay thế?

+0

Bạn có chắc là truy vấn có 'uniq' trả về kết quả khác không? Vui lòng hiển thị các truy vấn SQL thực tế cho mỗi biến thể (sử dụng phương thức 'sql'). – taro

+0

Tôi chắc chắn. Khi tôi sử dụng truy vấn này với cơ sở dữ liệu MySQL, vì vậy không có '.uniq' nó trả lại cho tôi cũng cùng một hàng, nhưng với' .uniq' luôn là hàng duy nhất. Trong PostgreSQL nếu tôi sử dụng '.uniq', tôi nhận được lỗi được chỉ định ở trên, nếu tôi không sử dụng' .uniq', vì vậy lỗi đã biến mất, nhưng tôi cũng nhận được các hàng tương tự từ DB. – user984621

Trả lời

30

Khi lỗi nêu rõ for SELECT DISTINCT, ORDER BY expressions must appear in select list. Vì vậy, bạn phải chọn rõ ràng cho mệnh đề bạn đang đặt hàng.

Đây là một ví dụ, nó tương tự như trường hợp của bạn nhưng tổng quát một chút.

Article.select('articles.*, RANDOM()') 
     .joins(:users) 
     .where(:column => 'whatever') 
     .order('Random()') 
     .uniq 
     .limit(15) 

Vì vậy, rõ ràng bao gồm khoản ORDER BY của bạn (trong trường hợp này RANDOM()) sử dụng .select(). Như được hiển thị ở trên, để truy vấn của bạn trả về thuộc tính Article, bạn phải chọn chúng một cách rõ ràng.

Tôi hy vọng điều này sẽ hữu ích; chúc may mắn

+2

Tại sao bạn thậm chí phải thêm những gì bạn đang đặt hàng theo mệnh đề lựa chọn ở vị trí đầu tiên trong postgresql. Nếu bạn đang sử dụng một tham gia, sau đó sql nên đủ thông minh để biết những gì để đặt hàng mà không khai báo rõ ràng nó trong mệnh đề select (đặc biệt là vì mệnh đề select được dùng để giới hạn các cột được trả về). – JohnMerlino

+0

Không bao gồm 'RANDOM()' hoàn toàn phủ nhận 'DISTINCT' vì nó lấy một tập hợp các giá trị hoàn toàn duy nhất vào tài khoản? Và như vậy bạn kết thúc với bản sao hồ sơ giống như nếu bạn đã không sử dụng 'DISTINCT' ở nơi đầu tiên? –

1

Tôi giả định rằng phương pháp .uniq được dịch sang mệnh đề DISTINCT trên SQL. PostgreSQL là cầu kỳ (pickier hơn MySQL) - tất cả các trường trong danh sách lựa chọn khi sử dụng DISTINCT phải có mặt trong các mệnh đề ORDER_BY (và GROUP_BY).

Đó là một chút không rõ ràng những gì bạn đang cố gắng làm (một thứ tự ngẫu nhiên?). Ngoài việc đăng toàn bộ câu lệnh SQL được gửi đi, nếu bạn có thể giải thích mục tiêu của mình, điều đó có thể hữu ích trong việc tìm kiếm giải pháp thay thế.

+0

Có lẽ bạn đúng, nhưng tồn tại bất kỳ cách thanh lịch nào để tích hợp trong truy vấn ở trên mệnh đề 'DISTINCT'? Truy vấn hiện tại của tôi là "khá ngắn", tôi có thể sử dụng 'find_by_sql' và có thẳng về phía trước để thiết lập' DISTINCT' clausule, nhưng trong trường hợp này sẽ là truy vấn lớn hơn nhiều. – user984621

0

Tôi vừa nâng cấp ứng dụng 100% đang hoạt động và thử nghiệm của mình từ 3.1.1 lên 3.2.7 và bây giờ có lỗi PG :: Lỗi này.

Tôi đang sử dụng Cancan ...

@users = User.accessible_by (current_ability) .order ('lname asc') uniq

Loại bỏ các .uniq giải quyết vấn đề và nó không cần thiết. dù sao cho truy vấn đơn giản này.

Vẫn xem qua các ghi chú thay đổi giữa 3.1.1 và 3.2.7 để xem điều gì đã gây ra lỗi này.

2

Chỉ để làm phong phú chuỗi với nhiều ví dụ hơn, trong trường hợp bạn có quan hệ lồng nhau trong truy vấn, bạn có thể thử với câu lệnh sau.

Person.find(params[:id]).cars.select('cars.*, lower(cars.name)').order("lower(cars.name) ASC") 

Trong ví dụ trên, bạn đang yêu cầu tất cả những chiếc xe cho một người nào đó, sắp xếp theo tên mô hình (Audi, Ferrari, Porsche)

Tôi không nghĩ rằng đây là một cách tốt hơn, nhưng có thể giúp giải quyết tình huống này suy nghĩ trong các đối tượng và các bộ sưu tập, thay vì một cách quan hệ (Cơ sở dữ liệu).

Cảm ơn!

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