sql >> Databáze >  >> RDS >> PostgreSQL

Rails 3.1 s PostgreSQL:GROUP BY musí být použit v agregační funkci

SQL generovaný výrazem není platný dotaz, seskupujete ho podle user_id a na základě toho vybrat spoustu dalších polí, ale neříkat DB, jak by měla agregovat ostatní pole. Pokud například vaše data vypadají takto:

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

Nyní, když požádáte db o seskupení podle a a také vrátí b, neví, jak agregovat hodnoty 1,2 . Musíte říct, jestli je potřeba vybrat min, max, průměr, součet nebo něco jiného. Právě když jsem psal odpověď, objevily se dvě odpovědi, které by to všechno mohly lépe vysvětlit.

Ve vašem případě použití si však myslím, že nechcete skupinu na úrovni db. Protože existuje pouze 10 umění, můžete je seskupit ve své aplikaci. Tuto metodu však nepoužívejte u tisíců umění:

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

UPRAVIT: Vyberte nejnovější_umění, ale pouze jedno umění na uživatele

Jen pro představu sql (netestoval jsem to, protože na svém systému nemám nainstalovaný RDBMS)

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

Toto řešení je založeno na praktickém předpokladu, že žádná dvě umění pro stejného uživatele nemohou mít stejnou nejvyšší created_at, ale může být špatně, pokud importujete nebo programově vytváříte velké množství umění. Pokud předpoklad neplatí, může být sql více vymyšlený.

UPRAVIT: Pokuste se změnit dotaz na 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. Získání průměru 10 nejlepších studentů z každé školy

  2. PDO odmítá smazat řádek dat (v konkrétní tabulce)

  3. Několik případů, kdy je výstup na stejném řádku

  4. Dvě levé spojení mi dávají nepravdivá data (dvojitá data?) s MySQL