Explicación del error
La causa inmediata del mensaje de error es que cualquier JOIN
explícito se une más fuerte que una coma (,
) que por lo demás es equivalente a CROSS JOIN
, pero (por documentación
):
Negrita énfasis mío.
Esta es la causa de su error. podrías arreglarlo:
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
Pero ese no fue el único problema. Sigue leyendo.
Se podría argumentar que Postgres debería ver que LATERAL
sólo tiene sentido en relación con la tabla de la izquierda. Pero eso no es así.
Suposición
Agregué alias de tabla y califiqué en la tabla todos los nombres de columna como sospechosos. Mientras lo hacía, simplifiqué las referencias JSON y recorté algo de ruido. Esta consulta todavía es incorrecta :
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 sin procesar
En base a lo anterior y algunas suposiciones más, la solución podría ser hacer el conteo en una 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 solo necesitas el conteo, convertí tu LATERAL
join en una subconsulta correlacionada, evitando así los diversos problemas que surgen de múltiples uniones 1:n combinadas. Más:
- ¿Cuál es la diferencia entre LATERAL JOIN y una subconsulta en PostgreSQL?
- Dos SQL LEFT JOINS producir un resultado incorrecto
Usted necesita para escapar de los identificadores correctamente, use una declaración preparada y pasar valores como valores. No concatene valores en la cadena de consulta. Esa es una invitación para errores aleatorios o inyección SQL ataques Ejemplo reciente para PHP: