web-dev-qa-db-fra.com

ERREUR: référence non valide à la clause FROM

J'ai la requête SQL (PostgreSQL) suivante:

SELECT ff.*, fp.*
FROM fibra ff, fibra fp

JOIN cables cp ON fp.cable_id = cp.id
LEFT OUTER JOIN terceiro  ced_pai ON ced_pai.id = cp.cedente_id
LEFT OUTER JOIN terceiro tp ON tp.id = fp.terceiro_id

JOIN cables cf ON ff.cable_id = cf.id
LEFT OUTER JOIN terceiro ced_f ON ced_f.id = cf.cedente_id
LEFT OUTER JOIN terceiro tf ON tf.id = ff.terceiro_id

where ff.fibra_pai_id = fp.id 
AND ff.cable_id IN (8,9,10) 
AND fp.cable_id IN (8,9,10)

Mais cela me donne cette erreur:

ERROR:  invalid reference to FROM-clause entry for table "ff"
LINE 8:  JOIN cables cf ON ff.cable_id = cf.id
           ^
HINT:  There is an entry for table "ff", but it cannot be referenced from this part of the query.

********** Error **********

ERROR: invalid reference to FROM-clause entry for table "ff"
SQL state: 42P01
Hint: There is an entry for table "ff", but it cannot be referenced from this part of the query.
Character: 261

Est-ce que quelqu'un sait ce que je fais mal?

24
lcguida

Vous mélangez des JOIN implicites et explicites. Cela est généralement déroutant à lire et conduit à des problèmes inattendus d'ordre d'évaluation, comme vous venez de le découvrir.

Vous devez toujours utiliser la syntaxe JOIN ... ON Partout; éviter l'héritage FROM table1, table2. Si vous corrigez votre requête pour utiliser un JOIN explicite au lieu de FROM fibra ff, fibra fp, Par exemple FROM fibra ff INNER JOIN fibra fp ON (ff.fibra_pai_id = fp.id) et si vous omettez ff.fibra_pai_id = fp.id De la clause WHERE, vous devriez obtenir la valeur attendue résultat.

Voir cette question à laquelle A.H. a lié:

Le mélange des jointures explicites et implicites échoue avec "Il existe une entrée pour la table ... mais elle ne peut pas être référencée à partir de cette partie de la requête"

31
Craig Ringer

Convertissez toutes les jointures de votre requête pour qu'elles soient explicites afin d'éviter le problème que vous rencontrez - ne laissez pas certaines implicites et d'autres explicites.

Cela devrait fonctionner:

SELECT ff.*, fp.*
  FROM fibra ff

  JOIN fibra fp ON ff.fibra_pai_id = fp.id 

  JOIN cables cp ON fp.cable_id = cp.id
  LEFT OUTER JOIN terceiro  ced_pai ON ced_pai.id = cp.cedente_id
  LEFT OUTER JOIN terceiro tp ON tp.id = fp.terceiro_id

  JOIN cables cf ON ff.cable_id = cf.id
  LEFT OUTER JOIN terceiro ced_f ON ced_f.id = cf.cedente_id
  LEFT OUTER JOIN terceiro tf ON tf.id = ff.terceiro_id

WHERE
 ff.cable_id IN (8,9,10) 
 AND fp.cable_id IN (8,9,10)
1
Ray