sql >> Databáze >  >> RDS >> PostgreSQL

neplatný odkaz na položku klauzule FROM pro tabulku v dotazu Postgres

Vysvětlení chyby

Bezprostřední příčinou chybové zprávy je jakákoli explicitní JOIN vazba je silnější než čárka (, ), což je jinak ekvivalentní CROSS JOIN , ale (podle dokumentace ):

Tučné důraz můj.
Toto je příčina vaší chyby. Mohli byste opravit:

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

To ale nebyl jediný problém. Pokračujte ve čtení.

Někdo by mohl namítnout, že Postgres by měl vidět LATERAL má smysl pouze ve spojení s tabulkou vlevo. Ale není tomu tak.

Předpoklad

Přidal jsem aliasy tabulek a kvalifikoval jsem všechny názvy sloupců jako podezřelé. Během toho jsem zjednodušil reference JSON a ořezal nějaký šum. Tento dotaz je stále nesprávný :

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

Nezpracovaný dotaz

Na základě výše uvedeného a některých dalších předpokladů by řešením mohlo být provedení počítání v dílčím dotazu:

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;

Protože potřebujete pouze počet, převedl jsem váš LATERAL spojit do korelovaného poddotazu, čímž se vyhnete různým problémům vyplývajícím z více kombinovaných spojení 1:n. Více:

potřebujete aby byly identifikátory escape správně, použijte připravený příkaz a předat hodnoty jako hodnoty. Nezřetězujte hodnoty do řetězce dotazu. To je pozvánka na náhodné chyby nebo vložení SQL útoky. Nedávný příklad pro PHP:




  1. PostreSQL 10 se nespustí na Ubuntu 18.04 běžícím na Windows Subsystému pro Linux

  2. Načítání výpisu v kódování UTF-8 do MySQL

  3. Instalace Oracle 11g Release 2 Enterprise Edition na Windows 7 32-Bit

  4. Jak zajistím, aby dotaz nevracel nic, když neexistují žádné podmínky?