PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rails 3.1 mit PostgreSQL:GROUP BY muss in einer Aggregatfunktion verwendet werden

Die vom Ausdruck generierte SQL ist keine gültige Abfrage, Sie gruppieren nach user_id und basierend darauf viele andere Felder auswählen, aber der DB nicht mitteilen, wie sie die anderen Felder aggregieren soll. Wenn Ihre Daten beispielsweise so aussehen:

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

Wenn Sie jetzt db auffordern, nach a zu gruppieren und auch b zurückgeben, weiß es nicht, wie man die Werte 1,2 aggregiert . Sie müssen angeben, ob min, max, Durchschnitt, Summe oder etwas anderes ausgewählt werden muss. Gerade als ich die Antwort schrieb, gab es zwei Antworten, die das alles besser erklären könnten.

In Ihrem Anwendungsfall möchten Sie jedoch meiner Meinung nach keine Gruppe auf Datenbankebene. Da es nur 10 Künste gibt, können Sie diese in Ihrer Bewerbung gruppieren. Verwenden Sie diese Methode jedoch nicht mit Tausenden von Künsten:

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

BEARBEITEN: Wählen Sie „latest_arts“, aber nur ein Bild pro Benutzer

Nur um Ihnen eine Idee von sql zu geben (habe es nicht getestet, da ich kein RDBMS auf meinem System installiert habe)

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

Diese Lösung basiert auf der praktischen Annahme, dass keine zwei Kunstwerke für denselben Benutzer dieselbe höchste erstellte_at haben können, aber es kann durchaus falsch sein, wenn Sie eine Menge von Kunstwerken importieren oder programmgesteuert erstellen. Wenn die Annahme nicht zutrifft, wird die SQL möglicherweise künstlicher.

BEARBEITEN: Versuchen Sie, die Abfrage in Arel:

zu ändern
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])