PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Ungültiger Verweis auf FROM-Klauseleintrag für Tabelle in Postgres-Abfrage

Erklärung für den Fehler

Die unmittelbare Ursache für die Fehlermeldung ist, dass ein expliziter JOIN bindet stärker als ein Komma (, ), was ansonsten einem CROSS JOIN entspricht , aber (pro Dokumentation ):

Fett Hervorhebung von mir.
Das ist die Ursache Ihres Fehlers. Sie könnten beheben:

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

Aber das war nicht das einzige Problem. Lesen Sie weiter.

Man könnte argumentieren, dass Postgres diesen LATERAL sehen sollte nur in Verbindung mit der Tabelle links sinnvoll. Aber dem ist nicht so.

Annahme

Ich habe Tabellenaliase hinzugefügt und alle Spaltennamen wie vermutet tabellenqualifiziert. Dabei habe ich die JSON-Referenzen vereinfacht und etwas Rauschen entfernt. Diese Abfrage ist immer noch falsch :

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

Rohabfrage

Basierend auf den obigen und einigen weiteren Annahmen könnte die Lösung darin bestehen, die Zählung in einer Unterabfrage durchzuführen:

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;

Da du nur die Zählung benötigst, habe ich dein LATERAL umgewandelt Join in eine korrelierte Unterabfrage, wodurch die verschiedenen Probleme vermieden werden, die sich aus der Kombination mehrerer 1:n-Joins ergeben. Mehr:

Sie brauchen Um Bezeichner richtig zu maskieren, verwenden Sie eine vorbereitete Anweisung und Werte übergeben als Werte. Verketten Sie keine Werte in der Abfragezeichenfolge. Das ist eine Einladung für zufällige Fehler oder SQL-Injektion Anschläge. Aktuelles Beispiel für PHP: