PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

referência inválida à entrada da cláusula FROM para tabela na consulta Postgres

Explicação do erro


A causa imediata para a mensagem de erro é que qualquer JOIN explícito liga mais forte que uma vírgula (, ) que é equivalente a um CROSS JOIN , mas (por documentação ):

Negrito ênfase minha.
Esta é a causa do seu erro. Você poderia consertá-lo:
FROM  appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...

Mas esse não foi o único problema. Continue lendo.

Pode-se argumentar que o Postgres deveria ver que LATERAL só faz sentido em conexão com a tabela à esquerda. Mas não é assim.

Suposição


Adicionei aliases de tabela e qualifiquei todos os nomes de coluna como suspeitos. Enquanto isso, simplifiquei as referências JSON e reduzi alguns ruídos. Esta consulta ainda está incorreta :
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

Consulta bruta


Com base no acima e em mais algumas suposições, a solução poderia ser fazer a contagem em uma subconsulta:
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;

Como você só precisa da contagem, converti seu LATERAL join em uma subconsulta correlacionada, evitando assim os vários problemas decorrentes de várias junções 1:n combinadas. Mais:

Você precisa para escapar dos identificadores corretamente, use uma instrução preparada e passar valores como valores. Não concatene valores na string de consulta. Isso é um convite para erros aleatórios ou injeção de SQL ataques. Exemplo recente para PHP: