2013-08-05 11 views
26

Ricevo questo errore nella modalità di produzione pg, ma funziona correttamente nella modalità di sviluppo sqlite3.PostgreSQL: deve apparire nella clausola GROUP BY o essere utilizzato in una funzione di aggregazione

ActiveRecord::StatementInvalid in ManagementController#index 

PG::Error: ERROR: column "estates.id" must appear in the GROUP BY clause or be used in an aggregate function 
LINE 1: SELECT "estates".* FROM "estates" WHERE "estates"."Mgmt" = ... 
      ^
: SELECT "estates".* FROM "estates" WHERE "estates"."Mgmt" = 'Mazzey' GROUP BY user_id 

@myestate = Estate.where(:Mgmt => current_user.Company).group(:user_id).all 
+2

con GROUP BY in PostgreSQL, non è possibile utilizzare la colonna nell'elenco di selezione se non lo si utilizza in gruppo per. Non so come tradurlo in rotaie –

+0

Correlati: http://stackoverflow.com/q/19601948/398670 –

+0

Possibile duplicato: http://stackoverflow.com/questions/19601948/must-appear-in-the- group-by-clause-or-be-used-in-an-aggregate-function –

risposta

3
@myestate1 = Estate.where(:Mgmt => current_user.Company) 
@myestate = @myestate1.select("DISTINCT(user_id)") 

questo è quello che ho fatto.

41

Se user_id è la PRIMARY KEY allora è necessario aggiornare PostgreSQL; le versioni più recenti gestiranno correttamente il raggruppamento con la chiave primaria.

Se user_id non è né unico né la chiave primaria per la relazione 'proprietà' in questione, allora questa query non ha molto senso, dal momento che PostgreSQL non ha modo di sapere che valore da restituire per ogni colonna di estates dove più righe condividono lo stesso user_id. È necessario utilizzare una funzione di aggregazione che esprima ciò che si desidera, ad esempio min, max, avg, string_agg, array_agg, ecc. O aggiungere la/le colonna/i di interesse allo GROUP BY.

In alternativa è possibile riformulare la query per utilizzare DISTINCT ON e un ORDER BY se si desidera effettivamente selezionare una riga un po 'arbitraria, anche se dubito davvero che sia possibile esprimerlo tramite ActiveRecord.

Alcuni database, tra cui SQLite e MySQL, selezionano solo una riga arbitraria. Questo è considerato non corretto e non sicuro dal team di PostgreSQL, quindi PostgreSQL segue lo standard SQL e considera tali query come errori.

se si dispone di:

col1 col2 
fred 42 
bob  9 
fred 44 
fred 99 

e lo fai:

SELECT col1, col2 FROM mytable GROUP BY col1; 

allora è ovvio che si dovrebbe ottenere la riga:

bob  9 

ma per quanto riguarda il risultato fred ? Non esiste un'unica risposta corretta da selezionare, quindi il database rifiuterà di eseguire query non sicure. Se si voleva la grandecol2 per qualsiasi col1 devi utilizzare il max aggregata:

SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1; 
+0

user_id è la chiave primaria nella tabella User, ma nella tabella di proprietà. –

+0

@HrishikeshSardar, nel qual caso questa query non ha senso. Quale proprietà viene restituita per ogni dato 'user_id'? Scegline uno a caso? Non lo farà. Devi usare un aggregato o ripensare a quello che stai facendo. –

+0

Sto cercando di capire è come se ho @estate con valori come {1,1,2,3,4,5,6,6}, ma ora voglio solo {1,2,3,4,5 , 6} da esso, cosa dovrei fare, in questo esempio ho dato ua array, ma voglio la stessa cosa per array di hash –

14

Recentemente mi sono trasferito da MySQL a PostgreSQL e ho riscontrato lo stesso problema. Solo per riferimento, l'approccio migliore che ho trovato è quello di usare distinti su come suggerito in questo SO risposta:

Elegant PostgreSQL Group by for Ruby on Rails/ActiveRecord

Questo vi permetterà di ottenere un record per ogni valore unico nella colonna scelta che corrisponde al altre condizioni di query:

MyModel.where(:some_col => value).select("DISTINCT ON (unique_col) *") 

Preferisco DISTINTO perché posso ancora ottenere tutti gli altri valori di colonna nella riga. DISTINCT da solo restituirà solo il valore di quella colonna specifica.

+1

'DISTINCT ON' è utile, se necessario. Ma il pianificatore di query non è così intelligente con 'DISTINCT ON' come con' DISTINCT' o 'GROUP BY', quindi vale la pena di evitarlo a meno che non sia effettivamente necessario. È anche non standard. –

6

Dopo aver ricevuto spesso l'errore, mi sono reso conto che Rails (sto usando i binari 4) aggiunge automaticamente un 'ordine di id' alla fine della query di raggruppamento. Ciò spesso provoca l'errore sopra. Quindi assicurati di aggiungere il tuo .order (: group_by_column) alla fine della tua query Rails. Quindi avrai qualcosa di simile a questo:

@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username') 
+5

Ho avuto lo stesso (default_scope che ha ordinato il mio modello). Quindi quello che ho fatto è: 'Model.reorder (nil) .gruppo_by (...)' in questo modo l'ordine viene rimosso. – Mosselman

+0

questo commento ... dovrebbe essere la risposta. – Dudo

Problemi correlati