2012-03-18 11 views
14

devo seguente query:Rails 3, ActiveRecord, PostgreSQL - Il comando ".uniq" non funziona?

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15).uniq 

e mi dà l'errore

PG::Error: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list 
LINE 1: ...s"."user_id" WHERE (articles.user_id != 1) ORDER BY Random() L... 

Quando ho aggiorno la query originale per

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15)#.uniq 

quindi l'errore è andato ... In MySQL .uniq funziona, in PostgreSQL no. Esiste qualche alternativa?

+0

Sei sicuro che la query con 'uniq' restituisce risultati diversi? Mostra le query SQL effettive per ogni variante (usa il metodo 'sql'). – taro

+0

Sono sicuro. Quando ho usato questa query con il database MySQL, quindi senza '.uniq' mi ha restituito anche la stessa riga, ma con' .uniq' sempre una riga univoca. In PostgreSQL se uso '.uniq', ottengo l'errore specificato sopra, se non uso' .uniq', quindi l'errore è sparito, ma sto ottenendo anche le stesse file dal DB. – user984621

risposta

30

Come l'errore indica for SELECT DISTINCT, ORDER BY expressions must appear in select list. Pertanto, è necessario selezionare esplicitamente la clausola che si sta ordinando.

Ecco un esempio, è simile al tuo caso ma generalizza un po '.

Article.select('articles.*, RANDOM()') 
     .joins(:users) 
     .where(:column => 'whatever') 
     .order('Random()') 
     .uniq 
     .limit(15) 

Quindi, includere esplicitamente il tuo clausola ORDER BY (in questo caso RANDOM()) utilizzando .select(). Come mostrato sopra, affinché la tua query restituisca gli attributi dell'articolo, devi anche selezionarli esplicitamente.

Spero che questo aiuti; buona fortuna

+2

Perché è necessario aggiungere anche ciò che si ordina alla clausola select al primo posto in postgresql. Se si sta utilizzando un join, lo sql dovrebbe essere abbastanza intelligente da sapere cosa ordinare, senza dichiararlo esplicitamente nella clausola select (soprattutto perché la clausola select intende limitare le colonne restituite). – JohnMerlino

+0

L'inclusione di 'RANDOM()' non annulla completamente il 'DISTINCT' perché prende in considerazione un insieme di valori completamente unici? E in quanto tale finisci con i duplicati come se non avessi usato il 'DISTINCT' in primo luogo? –

1

Suppongo che il metodo .uniq sia tradotto in una clausola DISTINCT su SQL. PostgreSQL è pignolo (più selettivo di MySQL) - tutti i campi nell'elenco di selezione quando si utilizza DISTINCT devono essere presenti nelle clausole ORDER_BY (e GROUP_BY).

È poco chiaro che cosa si sta tentando di fare (un ordinamento casuale?). Oltre a pubblicare l'SQL completo inviato, se puoi spiegare il tuo obiettivo, potrebbe essere utile per trovare un'alternativa.

+0

Probabilmente hai ragione, ma esiste un modo elegante di integrarsi nella query sopra la clausola 'DISTINCT'? La mia query corrente è "abbastanza breve", posso usare 'find_by_sql' e lì avanti per impostare la clausola' DISTINCT', ma in questo caso la query sarebbe molto più grande. – user984621

0

Ho appena aggiornato la mia applicazione funzionante al 100% dalla 3.1.1 alla 3.2.7 e ora ho lo stesso errore PG ::.

Sto usando Cancan ...

@users = User.accessible_by (current_ability) .order ('lname asc'). Uniq

Rimozione del .uniq risolve il problema e non era necessario comunque per questa semplice domanda.

Ancora guardando attraverso le note di modifica tra 3.1.1 e 3.2.7 per vedere cosa ha causato questo a rompere.

2

Giusto per arricchire il thread con altri esempi, nel caso in cui si abbiano relazioni nidificate nella query, si può provare con la seguente dichiarazione.

Person.find(params[:id]).cars.select('cars.*, lower(cars.name)').order("lower(cars.name) ASC") 

Nell'esempio riportato, si sta chiedendo tutte le macchine per una data persona, ordinati per nome del modello (Audi, Ferrari, Porsche)

Non credo che questo sia un modo migliore, ma può aiutare ad affrontare questo tipo di situazione pensando in oggetti e collezioni, invece che in un modo relazionale (database).

Grazie!

Problemi correlati