2010-04-23 3 views
5

Heroku를 사용하려고하고 있으며 분명히 Postgresql은 집계 함수에 대해 SQL보다 훨씬 엄격합니다. 내가 Heroku를 밀고있을 때 아래에 오류가 표시됩니다.Group by 절에 테이블 열 추가하기 - Ruby on Rails - Postgresql

On another question 나는 내가 단지 내 그룹 by 절에 열을 추가해야한다고 말한 몇 가지 지침을 받았는데 어떻게해야할지 모르겠다. 아래의 전체 오류 및 PostsControll # 색인을 참조하십시오. 가 PostsController

def index 
    @tag_counts = Tag.count(:group => :tag_name, 
     :order => 'count_all DESC', :limit => 20) 
     conditions, joins = {}, :votes 

    @ugtag_counts = Ugtag.count(:group => :ugctag_name, 
     :order => 'count_all DESC', :limit => 20) 
     conditions, joins = {}, :votes 

    @vote_counts = Vote.count(:group => :post_title, 
      :order => 'count_all DESC', :limit => 20) 
      conditions, joins = {}, :votes 


     unless(params[:tag_name] || "").empty? 
     conditions = ["tags.tag_name = ? ", params[:tag_name]] 
     joins = [:tags, :votes] 
     end 
     @posts=Post.paginate(
       :select => "posts.*, count(*) as vote_total", 
       :joins => joins, 
       :conditions=> conditions, 
       :group => "votes.post_id", 
       :order => "created_at DESC", 
       :page => params[:page], :per_page => 5) 
     @popular_posts=Post.paginate(
       :select => "posts.*, count(*) as vote_total", 
       :joins => joins, 
       :conditions=> conditions, 
       :group => "votes.post_id", 
       :order => "vote_total DESC", 
       :page => params[:page], :per_page => 3) 

    respond_to do |format| 
     format.html # index.html.erb 
     format.xml { render :xml => @posts } 
     format.json { render :json => @posts } 
     format.atom 
    end 
    end 

답변

3

MySQL과 SQLite는 매우 유연하여 GROUP BY 절에 이름이 지정되지 않고 선택 목록에있는 열을 허용합니다 (COUNT()과 같은 집계 함수에는 포함되지 않음). 그러나 이러한 유연성의 수준은 모호한 쿼리로 이어질 수 있습니다.

PostgreSQL은 ANSI SQL 표준과 같이 엄격합니다. 필자가 테스트 한 다른 모든 데이터베이스 (Oracle, Microsoft, IBM DB2, Firebird)는이 문제에 대해 PostgreSQL처럼 작동합니다.

선택 목록에있는 posts 열의 목록을 GROUP BY 절에 지정된 열과 일치 시키면됩니다. 더 적은 수의 열을 선택하거나 :group에 열을 추가하여이 작업을 수행하십시오.

저는 Rails 전문가가 아니며, 복수 열을 :group의 인수로 전달하는 방법의 예를 찾을 수 없습니다. active_record/base.rb에 대한 코드를 보면 단순히 옵션 값을 리터럴 SQL GROUP BY 절로 복사하는 것처럼 보입니다. 그래서 나는 (그것을 시도하지 않고) 당신이 할 수있는 가정합니다 :

... 
:group => "posts.post_id, posts.foo, posts.bar, posts.baz", 
... 

참고가 당신이 집계 함수의 일부가 아닌 당신의 선택 목록에있는 모든 열 이름을 가질 수. 나는 테이블 이름이 컴파일시에 동적으로보다는 악마에 가입 만드는 작업이 포함 변형 함께했다

group_models = [Post, Vote, etc.] 
group_columns = ['"votes"."post_id"'] # whatever column you were specifying with :group 
group_models.each do |model| 
    group_columns += model.column_names.map { |col| "\"#{model.table_name}\".\"#{col.name}\"" } 
end 
Post.where(whatever...).group(group_columns) 
+0

그랬습니다. 정말 감사합니다. 다음 호를 별도의 질문으로 게시하려고합니다. – bgadoci

+0

저는 항상 그룹화 된 열을 나열하기 위해 간단한 문자열을 사용했습니다. –

1

SELECT posts.*, count(*) as vote_total FROM "posts" INNER JOIN "votes" ON votes.post_id = posts.id GROUP BY votes.post_id ORDER BY created_at DESC LIMIT 5 OFFSET 0): 

방금 ​​posts.id 예를 사용하여 전환 시도 유무 :

SELECT posts.*, count(*) as vote_total FROM "posts" INNER JOIN "votes" ON votes.post_id = posts.id GROUP BY posts.id ORDER BY created_at DESC LIMIT 5 OFFSET 0); 

그렇다면, 어떻게 다음 결과 집합 당신이 얻고있는 것과 다를 않습니다 기존 SQL과 함께?

+0

나는 단지 ID를 게시하기 위해 : group => "votes.post_id"를 변경하려고 시도했지만 그 그룹을 클릭하고 URL/tag_name을 보낼 때 중단됩니다. 다음은 오류입니다 : SQLite3 :: SQLException : 모호한 열 이름 : post_id : 게시물 선택. *, count (*) vote_total FROM "posts"INNER JOIN "태그"ON tags.post_id = posts.id INNER JOIN "votes"ON votes.post_id = posts.id WHERE (tags.tag_name = '가장 최근의 태그') GROUP BY post_id ORDER BY created_at DESC LIMIT 5 OFFSET 0 – bgadoci

+0

aha - 글쎄 그게 당신이 votes.post_id 또는 tags.post_id 이렇게 말해야합니다. –

+0

이것은 여전히 ​​PostgreSQL에서 작동하지 않습니다. posts.id가 기본 키인 경우 PostgreSQL 9.1에서 작동합니다. –

0

는 여기에 내가 생각 해낸 해결책이다

model_columns = Model.column_names.collect do |c| "#{Model.table_name}.#{c}" end.join(",")

1

:

난 그냥 레일 (3)에서이 문제를 처리했다