sql >> Databasteknik >  >> RDS >> PostgreSQL

Rails 3.1 med PostgreSQL:GROUP BY måste användas i en aggregerad funktion

SQL-koden som genereras av uttrycket är inte en giltig fråga, du grupperar efter user_id och välja många andra fält baserat på det men inte berätta för DB hur den ska aggregera de andra filerna. Till exempel, om din data ser ut så här:

a  | b
---|---
1  | 1
1  | 2
2  | 3

Nu när du ber db att gruppera efter a och även returnera b, den vet inte hur man aggregerar värden 1,2 . Du måste berätta om den behöver välja min, max, medel, summa eller något annat. Precis när jag skrev svaret har det kommit två svar som kanske förklarar allt detta bättre.

I ditt användningsfall tror jag dock att du inte vill ha en grupp på db-nivå. Eftersom det bara finns 10 konster kan du gruppera dem i din ansökan. Använd dock inte den här metoden med tusentals konster:

 arts = Art.all(:order => "created_at desc", :limit => 10)
 grouped_arts = arts.group_by {|art| art.user_id}
 # now you have a hash with following structure in grouped_arts
 # { 
 #    user_id1 => [art1, art4],
 #    user_id2 => [art3],
 #    user_id3 => [art5],
 #    ....
 # }

EDIT: Välj latest_arts, men bara en konst per användare

Bara för att ge dig idén om sql (har inte testat det eftersom jag inte har RDBMS installerat på mitt system)

SELECT arts.* FROM arts
WHERE (arts.user_id, arts.created_at) IN 
  (SELECT user_id, MAX(created_at) FROM arts
     GROUP BY user_id
     ORDER BY MAX(created_at) DESC
     LIMIT 10)
ORDER BY created_at DESC
LIMIT 10

Denna lösning är baserad på det praktiska antagandet att inga två konster för samma användare kan ha samma högsta create_at, men det kan mycket väl vara fel om du importerar eller programmässigt skapar en stor del av konsten. Om antagandet inte stämmer, kan sql bli mer konstruerad.

EDIT: Försök att ändra frågan till Arel:

Art.where("(arts.user_id, arts.created_at) IN 
             (SELECT user_id, MAX(created_at) FROM arts
                GROUP BY user_id
                ORDER BY MAX(created_at) DESC
                LIMIT 10)").
    order("created_at DESC").
    page(params[:page]).
    per(params[:per])


  1. Oracle current_timestamp till sekunder konvertering

  2. SQL UNION-klausul för nybörjare

  3. Hur gör denna eav-fråga för att göra horisontella resultat

  4. Problem med en datumextraktion i SQL Server