Explication de l'erreur
La cause immédiate du message d'erreur est que tout JOIN
explicite lie plus fort qu'une virgule (,
) qui est autrement équivalent à un CROSS JOIN
, mais (par documentation
):
Gras c'est moi qui souligne.
C'est la cause de votre erreur. Vous pourriez corrigez-le :
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
Mais ce n'était pas le seul problème. Continuez à lire.
On pourrait dire que Postgres devrait voir que LATERAL
n'a de sens qu'en relation avec le tableau de gauche. Mais ce n'est pas le cas.
Hypothèse
J'ai ajouté des alias de table et qualifié tous les noms de colonne comme suspect. Pendant que j'y étais, j'ai simplifié les références JSON et réduit le bruit. Cette requête est toujours incorrecte :
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
Requête brute
Sur la base de ce qui précède et de quelques autres hypothèses, la solution pourrait être de faire le décompte dans une sous-requête :
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;
Comme vous n'avez besoin que du décompte, j'ai converti votre LATERAL
joindre dans une sous-requête corrélée, évitant ainsi les divers problèmes résultant de plusieurs jointures 1:n combinées. Plus :
- Quelle est la différence entre LATERAL JOIN et une sous-requête dans PostgreSQL ?
- Deux SQL LEFT JOINS produire un résultat incorrect
Vous avez besoin pour échapper correctement les identifiants, utilisez une instruction préparée et transmettez des valeurs comme valeurs. Ne concaténez pas les valeurs dans la chaîne de requête. C'est une invitation aux erreurs aléatoires ou à l'injection SQL attaques. Exemple récent pour PHP :