2009-06-30 16 views
14

Ho questa query che funziona correttamente in MySQL. Più sfondo su di esso here.Conversione di MySQL selezionare PostgreSQL

SELECT c.*, SUM(ABS(v.vote)) AS score 
FROM categories c,items i, votes v 
    WHERE c.id = i.category_id 
    AND i.id = v.voteable_id 
    AND v.created_at > '#{1.week.ago}' 
GROUP BY c.id 
ORDER BY score DESC LIMIT 8; 

Ho provato a eseguirlo in PostgreSQL e non è riuscito con questo messaggio di errore.

PGError: ERROR: column "c.name" must appear in the GROUP BY clause or be used in an aggregate function

non ero sicuro cosa significava, così ho provato a cambiare "c.id" a "c.name" nel gruppo dalla clausola (entrambi lavorano in MySQL stesso, assumendo il nome di un elemento è unico).

Tuttavia questo solo prodotto un altro errore simile

PGError: ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function

Come può questo problema essere risolto?

+1

Stranamente, sembra che questo sia ora consentito in Postgre 9.1 – you786

+0

È stato rimosso in Postgre 9.2? Ricevo questo errore per gli stessi motivi. – Aaron

+1

@Aaron: non è stato rimosso ma funziona solo quando (citando la [documentazione] (http://www.postgresql.org/docs/current/static/sql-select.html)): _la colonna non raggruppata dipende funzionalmente dalle colonne raggruppate, poiché altrimenti ci sarebbe più di un possibile valore da restituire per una colonna non raggruppata. Esiste una dipendenza funzionale se le colonne raggruppate (o un sottoinsieme di esse) sono la chiave primaria della tabella che contiene la colonna non raggruppata_ –

risposta

11

Bisogna elencare i nomi di colonna in selezionare quale si raggruppa in:

SELECT c.id, c.name, SUM(ABS(v.vote)) AS score 
FROM categories c,items i, votes v 
    WHERE c.id = i.category_id 
    AND i.id = v.voteable_id 
    AND v.created_at > '#{1.week.ago}' 
GROUP BY c.id, c.name 
ORDER BY score DESC LIMIT 8; 

"Non è consentito includere i nomi colonna in una clausola SELECT che non sono riferimento nella clausola GROUP BY"

+9

È consentito in MySQL ed è per questo che è confuso. Caratteristica orribile secondo me – colithium

+0

Questo ha funzionato, grazie! –

8

Ho appena avuto quel problema, ma passando da MySQL a SQL Server. Ho pensato che fosse permesso che fosse strano!

Sì, nella maggior parte dei database, quando si ha una clausola GROUP BY, è possibile selezionare solo gli aggregati di colonne o colonne visualizzati nella clausola GROUP BY. Questo perché non ha modo di sapere se le altre colonne che stai selezionando sono veramente uniche o meno.

Basta mettere le colonne che vuoi nel GROUP BY se sono davvero uniche. Questa era una "caratteristica" di MySQL che era discutibile.

È possibile leggere il comportamento di MySQL e come è diverso here.

Esempio:

SELECT c.*, SUM(ABS(v.vote)) AS score 
FROM categories c,items i, votes v 
    WHERE c.id = i.category_id 
    AND i.id = v.voteable_id 
    AND v.created_at > '#{1.week.ago}' 
GROUP BY c.id, c.name, c.whatever_else 
ORDER BY score DESC LIMIT 8; 
+0

Grazie per il collegamento MySQL, ora ha più senso! In questo caso il mio c.id è sempre unico quindi probabilmente era ok, ma almeno adesso so perché lo hanno fatto. Grazie! –

2

Se si cambia la vostra dichiarazione a questo dovrebbe funzionare:

SELECT c.id, SUM(ABS(v.vote)) AS score 
FROM categories c,items i, votes v 
    WHERE c.id = i.category_id 
    AND i.id = v.voteable_id 
    AND v.created_at > '#{1.week.ago}' 
GROUP BY c.id 
ORDER BY score DESC LIMIT 8; 

Non sono sicuro di quello che MySQL dà come risultato, ma per darvi una piccola esempio del perché questo non funziona in PostgreSQL, date un'occhiata al categories seguente tabella:

id | name 
---|----- 
1 | ABC 
1 | DEF 

Raggruppa per id, quindi ogni riga del risultato deve contenere solo uno id. Se si seleziona anche name, senza raggruppamento, cosa deve essere visualizzato nel risultato per name?

Può essere sia ABC o DEF ma il motore di database non può davvero decidere ciò per voi (sebbene apparentemente MySQL).

+1

MySQL ne sceglie uno a caso! Non è strano? Ho fatto una domanda a riguardo qualche giorno fa. – colithium

+0

Non sapevo nemmeno che fosse così. Molto strano ... –

+0

Interessante ... in questo caso almeno il mio id è sempre unico quindi era una buona colonna da raggruppare. Mi serviva anche il nome della categoria, quindi ho appena elencato sia nella selezione che nel gruppo per. Sembra funzionare. Grazie! –