Spiegazione dell'errore
La causa immediata del messaggio di errore è che qualsiasi JOIN
esplicito lega più forte di una virgola (,
) che è altrimenti equivalente a un CROSS JOIN
, ma (per documentazione
):
Grassetto enfasi mia.
Questa è la causa del tuo errore. Potresti aggiustalo:
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
Ma non era l'unico problema. Continua a leggere.
Si potrebbe obiettare che Postgres dovrebbe vederlo LATERAL
ha senso solo in connessione con la tabella a sinistra. Ma non è così.
Assunzione
Ho aggiunto alias di tabella e qualificato tabella tutti i nomi di colonna come sospettati. Mentre ci lavoravo, ho semplificato i riferimenti JSON e ridotto un po' di rumore. Questa query è ancora errata :
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
Query grezza
Sulla base di quanto sopra e di alcune altre ipotesi, la soluzione potrebbe essere quella di eseguire il conteggio in una sottoquery:
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;
Dato che ti serve solo il conteggio, ho convertito il tuo LATERAL
join in una subquery correlata, evitando così i vari problemi derivanti da più join 1:n combinati. Altro:
- Qual è la differenza tra LATERAL JOIN e una sottoquery in PostgreSQL?
- Due SQL LEFT JOINS produrre un risultato errato
Hai necessità per evadere correttamente gli identificatori, usa una istruzione preparata e passa valori come valori. Non concatenare i valori nella stringa di query. Questo è un invito per errori casuali o SQL injection attacchi. Esempio recente per PHP: