PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Rails 3.1 con PostgreSQL:GROUP BY deve essere utilizzato in una funzione aggregata

Lo sql generato dall'espressione non è una query valida, stai raggruppando per user_id e selezionando molti altri campi in base a quello, ma non dicendo al DB come dovrebbe aggregare gli altri campi. Ad esempio, se i tuoi dati sono così:

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

Ora quando chiedi a db di raggruppare per a e restituisce anche b, non sa come aggregare i valori 1,2 . Devi dire se deve selezionare min, max, media, somma o qualcos'altro. Proprio mentre stavo scrivendo la risposta ci sono state due risposte che potrebbero spiegare tutto questo meglio.

Nel tuo caso d'uso, però, penso che tu non voglia un gruppo a livello di db. Poiché ci sono solo 10 arti, puoi raggrupparle nella tua domanda. Tuttavia, non utilizzare questo metodo con migliaia di arti:

 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],
 #    ....
 # }

MODIFICA: Seleziona latest_arts, ma solo una grafica per utente

Giusto per darti l'idea di sql (non l'ho testato perché non ho RDBMS installato sul mio sistema)

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

Questa soluzione si basa sul presupposto pratico, che non ci sono due arti per lo stesso utente possono avere lo stesso valore più alto creato_at, ma potrebbe essere sbagliato se stai importando o creando in modo programmatico la maggior parte delle arti. Se l'ipotesi non è vera, sql potrebbe diventare più artificioso.

MODIFICA: Tentativo di modificare la query in 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])