2009-06-30 7 views
14

J'ai cette requête qui fonctionne correctement dans MySQL. Plus de fond à ce sujet here. J'ai essayé de l'exécuter dans PostgreSQL, et il a échoué avec ce message d'erreur.Conversion de MySQL select en PostgreSQL

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

Je ne savais pas ce que cela voulait dire, alors j'ai essayé de changer « c.id » à « c.name » dans le groupe par clause (à la fois dans MySQL même, en supposant que le nom d'un élément est unique).

Cependant, ce produit vient une autre erreur semblable

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

Comment ce problème peut être résolu?

+1

Bizarrement, il semble que cela soit maintenant autorisé dans Postgre 9.1 – you786

+0

A-t-il été supprimé dans Postgre 9.2? Je reçois cette erreur pour les mêmes raisons. – Aaron

+1

@Aaron: il n'a pas été supprimé mais fonctionne uniquement lorsque (en citant la [documentation] (http://www.postgresql.org/docs/current/static/sql-select.html)): _la colonne non groupée dépend fonctionnellement des colonnes groupées, puisqu'il y aurait autrement plus d'une valeur possible à retourner pour une colonne non groupée. Une dépendance fonctionnelle existe si les colonnes groupées (ou un sous-ensemble de celles-ci) sont la clé primaire de la table contenant la colonne dégroupée_ –

Répondre

11

Vous devez lister les noms de colonnes dans SELECT que vous groupez dans:

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; 

« Il est interdit d'inclure les noms de colonnes dans une clause SELECT qui ne sont pas référencées dans la clause GROUP BY. »

+9

C'est autorisé dans MySQL et c'est pourquoi il est confus. Horrible caractéristique à mon avis – colithium

+0

Cela a fonctionné, merci! –

8

Je viens d'avoir ce problème, mais aller de MySQL à SQL Server. Je pensais que le fait que cela soit permis c'était étrange!

Oui, dans la plupart des bases de données, lorsque vous avez une clause GROUP BY, vous pouvez uniquement sélectionner des agrégats de colonnes ou de colonnes qui apparaissent dans la clause GROUP BY. C'est parce qu'il n'a aucun moyen de savoir si les autres colonnes que vous sélectionnez sont vraiment uniques ou non.

Placez simplement les colonnes que vous voulez dans GROUP BY si elles sont uniques. C'était une "caractéristique" de MySQL qui était discutable.

Vous pouvez lire sur le comportement de MySQL et comment il est différent here.

Exemple:

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

Merci pour le lien MySQL, cela a plus de sens maintenant! Dans ce cas mon c.id est toujours unique donc c'était probablement ok, mais au moins je sais maintenant pourquoi ils l'ont fait. Merci! –

2

Si vous changez votre déclaration à ce qu'il devrait fonctionner:

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; 

Je ne sais pas ce que MySQL donne suite, mais pour vous donner une très petite exemple de pourquoi cela ne fonctionne pas dans PostgreSQL, jetez un oeil à la table categories suivante:

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

Vous groupez par id, de sorte que chaque ligne du résultat ne contienne qu'un seul id. Si vous sélectionnez également name, sans le grouper, que devrait-on voir dans le résultat pour name?

Il peut être soit ABC ou DEF mais le moteur de base de données ne peut pas vraiment décider cela pour vous (bien que MySQL semble le faire).

+1

MySQL choisit un aléatoire! N'est-ce pas étrange? J'ai posé une question à ce sujet il y a quelques jours. – colithium

+0

Je ne savais même pas que c'était le cas. Très étrange ... –

+0

Intéressant ... dans ce cas au moins mon id est toujours unique donc c'était une bonne colonne à grouper par. J'avais aussi besoin du nom de la catégorie, donc je viens d'énumérer les deux dans le select et le group by. Ça semble fonctionner. Merci! –