PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

référence invalide à l'entrée de la clause FROM pour la table dans la requête Postgres

Explication de l'erreur

La cause immédiate du message d'erreur est que tout JOIN explicite lie plus fort qu'une virgule (, ) qui est autrement équivalent à un CROSS JOIN , mais (par documentation ):

Gras c'est moi qui souligne.
C'est la cause de votre erreur. Vous pourriez corrigez-le :

FROM  appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...

Mais ce n'était pas le seul problème. Continuez à lire.

On pourrait dire que Postgres devrait voir que LATERAL n'a de sens qu'en relation avec le tableau de gauche. Mais ce n'est pas le cas.

Hypothèse

J'ai ajouté des alias de table et qualifié tous les noms de colonne comme suspect. Pendant que j'y étais, j'ai simplifié les références JSON et réduit le bruit. Cette requête est toujours incorrecte :

SELECT i.data ->> 'id'          AS id,
       i.data ->> 'name'        AS name,
       i.data ->> 'curator'     AS curator,
       i.data ->  '$isValid'    AS "$isValid",
       i.data ->  'customer'    AS customer,
       i.data ->  '$createdTS'  AS "$createdTS",
       i.data ->  '$updatedTS'  AS "$updatedTS",
       i.data ->  '$isComplete' AS "$isComplete",
       count(k.keys)::numeric   AS "numProducts",
       u.created_at
FROM   appointment_intakes i
     , jsonb_object_keys(i.data -> 'products') AS k(keys)
JOIN   appointment_intake_users u ON u.appointment_intake_id = i.id
#{where_clause}
GROUP  BY i.id

Requête brute

Sur la base de ce qui précède et de quelques autres hypothèses, la solution pourrait être de faire le décompte dans une sous-requête :

SELECT i.data ->> 'id'          AS id,
       i.data ->> 'name'        AS name,
       i.data ->> 'curator'     AS curator,
       i.data ->  '$isValid'    AS "$isValid",
       i.data ->  'customer'    AS customer,
       i.data ->  '$createdTS'  AS "$createdTS",
       i.data ->  '$updatedTS'  AS "$updatedTS",
       i.data ->  '$isComplete' AS "$isComplete",
       (SELECT count(*)::numeric
        FROM   jsonb_object_keys(i.data -> 'products')) AS "numProducts",
       min(u.created_at)        AS created_at
FROM   appointment_intakes i
JOIN   appointment_intake_users u ON u.appointment_intake_id = i.id
--     #{where_clause}
GROUP  BY i.id;

Comme vous n'avez besoin que du décompte, j'ai converti votre LATERAL joindre dans une sous-requête corrélée, évitant ainsi les divers problèmes résultant de plusieurs jointures 1:n combinées. Plus :

Vous avez besoin pour échapper correctement les identifiants, utilisez une instruction préparée et transmettez des valeurs comme valeurs. Ne concaténez pas les valeurs dans la chaîne de requête. C'est une invitation aux erreurs aléatoires ou à l'injection SQL attaques. Exemple récent pour PHP :