Giải thích cho lỗi
Nguyên nhân ngay lập tức cho thông báo lỗi là bất kỳ JOIN
rõ ràng nào liên kết mạnh hơn dấu phẩy (,
) tương đương với CROSS JOIN
, nhưng ( theo tài liệu
):
In đậm nhấn mạnh của tôi.
Đây là nguyên nhân gây ra lỗi của bạn. Bạn có thể sửa nó:
FROM appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...
Nhưng đó không phải là vấn đề duy nhất. Hãy tiếp tục đọc.
Người ta có thể tranh luận rằng Postgres nên thấy rằng LATERAL
chỉ có ý nghĩa liên quan đến bảng bên trái. Nhưng không phải vậy.
Giả định
Tôi đã thêm bí danh bảng và tất cả các tên cột đủ điều kiện bảng như nghi ngờ. Trong khi thực hiện, tôi đã đơn giản hóa các tham chiếu JSON và cắt bớt một số nhiễu. Truy vấn này vẫn không chính xác :
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
Truy vấn thô
Dựa trên những điều trên và một số giả định khác, giải pháp có thể là thực hiện đếm trong một truy vấn con:
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;
Vì bạn chỉ cần số lượng, nên tôi đã chuyển đổi LATERAL
của bạn nối vào một truy vấn con tương quan, do đó tránh được các vấn đề khác nhau phát sinh từ nhiều phép nối 1:n kết hợp với nhau. Thêm:
- Sự khác biệt giữa LATERAL JOIN và truy vấn con trong PostgreSQL là gì?
- Hai SQL LEFT JOINS tạo ra kết quả không chính xác
Bạn cần để thoát khỏi số nhận dạng đúng cách, hãy sử dụng câu lệnh đã soạn sẵn và chuyển giá trị như các giá trị. Không nối các giá trị vào chuỗi truy vấn. Đó là lời mời cho các lỗi ngẫu nhiên hoặc Chèn SQL các cuộc tấn công. Ví dụ gần đây cho PHP: