Penjelasan untuk kesalahan
Penyebab langsung dari pesan kesalahan ini adalah JOIN
yang eksplisit mengikat lebih kuat dari koma (,
) yang setara dengan CROSS JOIN
, tetapi (per dokumentasi
):
Tebal penekanan saya.
Ini adalah penyebab kesalahan Anda. Anda bisa perbaiki:
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
Tapi itu bukan satu-satunya masalah. Teruslah membaca.
Orang mungkin berpendapat bahwa Postgres harus melihat bahwa LATERAL
hanya masuk akal sehubungan dengan tabel di sebelah kiri. Tapi bukan begitu.
Asumsi
Saya menambahkan alias tabel, dan tabel memenuhi syarat semua nama kolom seperti yang dicurigai. Saat melakukannya, saya menyederhanakan referensi JSON dan memangkas beberapa noise. Kueri ini masih salah :
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
Kueri mentah
Berdasarkan asumsi di atas dan beberapa asumsi lainnya, solusinya adalah melakukan penghitungan dalam subquery:
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;
Karena Anda hanya perlu menghitung, saya mengonversi LATERAL
. Anda bergabung menjadi subquery yang berkorelasi, sehingga menghindari berbagai masalah yang timbul dari beberapa gabungan 1:n digabungkan. Selengkapnya:
- Apa perbedaan antara LATERAL JOIN dan subquery di PostgreSQL?
- Dua SQL KIRI BERGABUNG menghasilkan hasil yang salah
Anda membutuhkan untuk menghindari pengidentifikasi dengan benar, gunakan pernyataan yang disiapkan dan berikan nilai sebagai nilai. Jangan gabungkan nilai ke dalam string kueri. Itu undangan untuk kesalahan acak atau injeksi SQL serangan. Contoh terbaru untuk PHP: