sql >> Database >  >> RDS >> PostgreSQL

ongeldige verwijzing naar FROM-clausule voor tabel in Postgres-query

Uitleg voor de fout

De directe oorzaak van de foutmelding is dat elke expliciete JOIN bindt sterker dan een komma (, ) wat anders gelijk is aan een CROSS JOIN , maar (per documentatie ):

Vet nadruk van mij.
Dit is de oorzaak van je fout. Je zou repareer het:

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

Maar dat was niet het enige probleem. Blijf lezen.

Je zou kunnen stellen dat Postgres zou moeten zien dat LATERAL heeft alleen zin in verband met de tabel links. Maar dat is niet zo.

Aanname

Ik voegde tabelaliassen toe en kwalificeerde alle kolomnamen als verdacht. Terwijl ik bezig was, heb ik de JSON-referenties vereenvoudigd en wat ruis bijgesneden. Deze zoekopdracht is nog steeds onjuist :

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

Onbewerkte zoekopdracht

Op basis van het bovenstaande en wat meer aannames, zou de oplossing kunnen zijn om de telling in een subquery uit te voeren:

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;

Omdat je alleen de telling nodig hebt, heb ik je LATERAL . geconverteerd join in een gecorreleerde subquery, waardoor de verschillende problemen worden vermeden die voortvloeien uit meerdere gecombineerde 1:n-joins. Meer:

Je hebt nodig gebruik een voorbereide instructie . om identifiers correct te escapen en geef waarden door als waarden. Voeg geen waarden samen in de querytekenreeks. Dat is een uitnodiging voor willekeurige fouten of SQL-injectie aanvallen. Recent voorbeeld voor PHP:




  1. Krijgen EXACTE overeenkomsten van zoeken in volledige tekst als eerste geretourneerd?

  2. Is er een verschil in het opslaan van dezelfde waarde in verschillende typen gehele getallen?

  3. Selecteer producten op meerdere attributen, gebruik AND in plaats van OR concatenator, Datamodel EAV

  4. Postgresql 11:Opgeslagen procedure-aanroepfout - Om een ​​procedure aan te roepen, gebruikt u CALL, Java