sql >> Base de Datos >  >> RDS >> PostgreSQL

Rails 3.1 con PostgreSQL:GROUP BY debe usarse en una función agregada

El sql generado por la expresión no es una consulta válida, está agrupando por user_id y seleccionar muchos otros campos en función de eso, pero no decirle a la base de datos cómo debe agregar los otros archivos. Por ejemplo, si sus datos se ven así:

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

Ahora, cuando le pides a db que agrupe por a y también devuelve b, no sabe cómo agregar valores 1,2 . Debe indicar si necesita seleccionar mínimo, máximo, promedio, suma u otra cosa. Justo cuando estaba escribiendo la respuesta, hubo dos respuestas que podrían explicar todo esto mejor.

Sin embargo, en su caso de uso, creo que no desea un grupo en el nivel de base de datos. Como solo hay 10 artes, puede agruparlas en su aplicación. Sin embargo, no uses este método con miles de artes:

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

EDITAR: Seleccione Latest_arts, pero solo un arte por usuario

Solo para darle una idea de sql (no lo he probado porque no tengo RDBMS instalado en mi 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

Esta solución se basa en la suposición práctica de que dos artes para el mismo usuario no pueden tener el mismo created_at más alto, pero puede ser incorrecto si está importando o creando programáticamente la mayor parte de las artes. Si la suposición no es cierta, el sql podría volverse más artificial.

EDITAR: Intente cambiar la consulta a 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])