sql >> Databasteknik >  >> RDS >> PostgreSQL

ogiltig referens till FROM-klausulpost för tabellen i Postgres-frågan

Förklaring till felet

Den omedelbara orsaken till felmeddelandet är att någon explicit JOIN binder starkare än ett kommatecken (, ) som annars motsvarar en CROSS JOIN , men (per dokumentation ):

Fet betoning min.
Detta är orsaken till ditt fel. Du kunde fixa det:

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

Men det var inte det enda problemet. Fortsätt läsa.

Man kan hävda att Postgres borde se den LATERAL är bara vettigt i samband med tabellen till vänster. Men så är det inte.

Antagande

Jag lade till tabellalias och tabellkvalificerade alla kolumnnamn som misstänkt. Medan jag var på gång förenklade jag JSON-referenserna och trimmade lite brus. Den här frågan är fortfarande felaktig :

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

Raw query

Baserat på ovanstående och några fler antaganden kan lösningen vara att räkna i en underfråga:

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;

Eftersom du bara behöver räkningen konverterade jag din LATERAL join till en korrelerad delfråga, och undviker därigenom de olika problemen som uppstår från kombinerade 1:n-kopplingar. Mer:

Du behöver för att undvika identifierare korrekt, använd en förberedd sats och skicka värden som värden. Sammanfoga inte värden i frågesträngen. Det är en inbjudan för slumpmässiga fel eller SQL-injektion attacker. Senaste exempel för PHP:




  1. Kör/kör flera procedurer i Parallell - Oracle PL/SQL

  2. LAST_INSERT_ID() returnerar alltid 0 (RMySQL) - separat anslutningsproblem

  3. percentil med COUNT(DISTINCT) med korrelerad WHERE fungerar bara med en vy (eller utan DISTINCT)

  4. Hur säkerhetskopierar jag min PostgreSQL-databas med Cron?