sql >> Database >  >> RDS >> PostgreSQL

Rails 3.1 met PostgreSQL:GROUP BY moet worden gebruikt in een aggregatiefunctie

De sql die door de expressie wordt gegenereerd, is geen geldige zoekopdracht, u groepeert op user_id en het selecteren van veel andere velden op basis daarvan, maar niet de DB vertellen hoe het de andere bestanden moet samenvoegen. Als uw gegevens er bijvoorbeeld zo uitzien:

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

Als je db nu vraagt ​​om te groeperen op a en geeft ook b terug, het weet niet hoe de waarden 1,2 . moeten worden geaggregeerd . U moet aangeven of het min, max, gemiddelde, som of iets anders moet selecteren. Net toen ik het antwoord aan het schrijven was, waren er twee antwoorden die dit allemaal beter zouden kunnen verklaren.

In jouw geval denk ik echter dat je geen group by op db-niveau wilt. Aangezien er slechts 10 kunsten zijn, kunt u ze groeperen in uw toepassing. Gebruik deze methode echter niet met duizenden kunsten:

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

BEWERK: Selecteer nieuwste_arts, maar slechts één kunst per gebruiker

Om je een idee te geven van sql (heb het niet getest omdat ik geen RDBMS op mijn systeem heb geïnstalleerd)

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

Deze oplossing is gebaseerd op de praktische aanname dat geen twee kunsten voor dezelfde gebruiker dezelfde hoogste create_at kunnen hebben, maar het kan wel eens verkeerd zijn als je een groot deel van de kunst importeert of programmatisch maakt. Als de aanname niet klopt, kan de sql meer gekunsteld worden.

BEWERKEN: Poging om de zoekopdracht te wijzigen 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])


  1. Substring gebruiken in MySQL-criteria

  2. oracle sql if condition selecteer dan statement1 else select statement2

  3. Oracle DELETE-instructie met subqueryfactoring

  4. Wat is de meest volwassen/stabiele mysql node.js-module?