PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

riferimento non valido alla voce della clausola FROM per la tabella nella query di Postgres

Spiegazione dell'errore

La causa immediata del messaggio di errore è che qualsiasi JOIN esplicito lega più forte di una virgola (, ) che è altrimenti equivalente a un CROSS JOIN , ma (per documentazione ):

Grassetto enfasi mia.
Questa è la causa del tuo errore. Potresti aggiustalo:

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

Ma non era l'unico problema. Continua a leggere.

Si potrebbe obiettare che Postgres dovrebbe vederlo LATERAL ha senso solo in connessione con la tabella a sinistra. Ma non è così.

Assunzione

Ho aggiunto alias di tabella e qualificato tabella tutti i nomi di colonna come sospettati. Mentre ci lavoravo, ho semplificato i riferimenti JSON e ridotto un po' di rumore. Questa query è ancora errata :

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

Query grezza

Sulla base di quanto sopra e di alcune altre ipotesi, la soluzione potrebbe essere quella di eseguire il conteggio in una sottoquery:

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;

Dato che ti serve solo il conteggio, ho convertito il tuo LATERAL join in una subquery correlata, evitando così i vari problemi derivanti da più join 1:n combinati. Altro:

Hai necessità per evadere correttamente gli identificatori, usa una istruzione preparata e passa valori come valori. Non concatenare i valori nella stringa di query. Questo è un invito per errori casuali o SQL injection attacchi. Esempio recente per PHP: