62 votes

MySQL colonne inconnue dans la clause ON

J'ai la requête MySQL suivante:

SELECT p.*,
    IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
    pm.MediaID,
    date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
    astext(pg.Geometry) AS Geometry
FROM property p, propertygeometry pg
    JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
    LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
    LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
    AND p.PropertyGeometryID = pg.id
GROUP BY p.id

Et je reçois cette erreur:

#1054 - Colonne 'p.id' inconnue dans la clause 'on'

Autant que je puisse voir, la requête semble correcte, avez-vous une idée de ce qui pourrait ne pas aller?

0 votes

Je suis certain que vous avez vérifié, mais vous avez bien une colonne id sur la table property qui est aliasée comme p ?

107voto

Mark Byers Points 318575

Ne mélangez pas les joints de style ANSI-89 et de style ANSI-92. Ils ont une précédence différente qui peut entraîner des erreurs confuses, et c'est ce qui s'est produit ici. Votre requête est interprétée comme suit :

FROM property p, (
    propertygeometry pg
    JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
    ...
)

Dans ce qui précède, les joints utilisant le mot-clé JOIN sont évalués en premier avant que le joint de style virgule ne soit même pris en compte. À ce moment-là, la table p n'est pas encore déclarée.

D'après le manuel de MySQL:

Cependant, la précédence de l'opérateur de virgule est inférieure à celle de INNER JOIN, CROSS JOIN, LEFT JOIN, etc. Si vous mélangez des joints de virgule avec les autres types de joint lorsqu'il y a une condition de joint, une erreur de type Colonne inconnue 'nom_colonne' dans la clause 'on' peut se produire. Des informations sur la manière de résoudre ce problème sont données plus tard dans cette section.

Je recommande toujours d'utiliser des joints de style ANSI-92, c'est-à-dire en utilisant le mot-clé JOIN :

SELECT p.*,
    IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
    pm.MediaID,
    date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
    astext(pg.Geometry) AS Geometry
FROM property p
    JOIN propertygeometry pg ON p.PropertyGeometryID = pg.id
    JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
    LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
    LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
GROUP BY p.id

Lié :

0 votes

Il n'existe pas de notion de "implicite" ou "explicite" en ce qui concerne la syntaxe JOIN.

17voto

Tom Mulkins Points 191

Comme indiqué précédemment, il y a un problème de préférence lors de l'utilisation de jointures via l'opérateur virgule où la LEFT JOIN sera exécutée et donc les références aux alias de table n'existeront pas à ce moment-là. Bien que vous puissiez implicitement indiquer à MySQL d'utiliser une JOIN via cette déclaration, vous pouvez également dire à MySQL d'évaluer d'abord les tables jointes par virgule, puis d'exécuter LEFT JOIN de la manière suivante :

SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM (property p, propertygeometry pg)
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
AND p.PropertyGeometryID = pg.id
GROUP BY p.id

Remarquez que les tables séparées par des virgules sont contenues entre parenthèses (). Les alias de table et les colonnes seront maintenant disponibles pour vos autres JOINs.

1voto

user742102 Points 258

J'ai rencontré cette erreur de colonne inconnue, la différence est que la requête est construite à travers HQL à l'intérieur de session.executeQuery("select id, name, sum(paid), custType from cust group by brand") c'est pourquoi devoir taper manuellement Inner Join ou Join n'est pas une option car c'est le HQL qui le génère. Cela produit une requête ressemblant à ceci:

select cust_id, name, sum(paid), c.custTypeId
from customer c, custType ct
on c.custTypeId  = ct.custTypeId 

il dit " colonne c.custTypeId" inconnue alors que je suis sûr à 101% qu'elle contient cette colonne.

Mes classes/relations:

Customer {
Integer custId
CustomerType custType
}

CustomerType{
 Integer custTypeId
string code
}

Le problème se situe dans la virgule de la ligne "from customer, custType", elle devrait être avec le mot JOIN comme la réponse l'a indiqué ci-dessus. Mais comme c'est du HQL et que c'est généré, je ne peux pas faire ça. Ce que j'ai fait c'est modifier ma requête et au lieu de taper select custType, j'ai tapé select custType.id, custType.code

Je sais que c'est basique mais pour les débutants comme moi, c'était une lutte.

0voto

John Kearney Points 36

Juste au cas où quelqu'un d'autre se tire une balle dans le pied comme ça.

J'étais nouveau sur MySQL Workbench et je testais un nouveau schéma, cependant je n'ai pas pensé à sélectionner d'ajouter les commandes DROP lors de la poussée vers le serveur pour les tests.

Ce qui signifiait que lorsque je modifiais mes tables et mettais à jour la vue, je continuais à obtenir ces erreurs étranges.

En résumé, assurez-vous réellement de mettre à jour le schéma de la table sur le serveur à chaque envoi pendant la phase de test initial, sinon votre nouvelle vue peut échouer en raison des anciennes tables sur le serveur.

-1voto

tejr Points 173

Il semble que ce champ ID pourrait en réalité ne pas exister - c'est-à-dire, la requête est structurellement valide mais fait référence à un champ inexistant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X