Đây là một mẹo:tính toán SUM()
của các giá trị được biết là 1 hoặc 0 tương đương với COUNT()
của các hàng có giá trị là 1. Và bạn biết rằng so sánh boolean trả về 1 hoặc 0 (hoặc NULL).
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
LEFT JOIN map m USING (catid)
LEFT JOIN items i USING (itemid)
GROUP BY c.catid;
Đối với câu hỏi phần thưởng, bạn có thể chỉ cần thực hiện một phép nối bên trong thay vì phép nối bên ngoài, nghĩa là chỉ các danh mục có ít nhất một hàng trong map
sẽ được trả lại.
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
INNER JOIN map m USING (catid)
INNER JOIN items i USING (itemid)
GROUP BY c.catid;
Đây là một giải pháp khác, không hiệu quả bằng nhưng tôi sẽ hiển thị nó để giải thích tại sao bạn gặp lỗi:
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
LEFT JOIN map m USING (catid)
LEFT JOIN items i USING (itemid)
GROUP BY c.catid
HAVING item_count > 0;
Bạn không thể sử dụng bí danh cột trong WHERE
mệnh đề, bởi vì các biểu thức trong WHERE
mệnh đề được đánh giá trước các biểu thức trong danh sách chọn. Nói cách khác, các giá trị được liên kết với các biểu thức danh sách chọn chưa có sẵn.
Bạn có thể sử dụng bí danh cột trong GROUP BY
, HAVING
và ORDER BY
điều khoản. Các mệnh đề này được chạy sau khi tất cả các biểu thức trong danh sách chọn đã được đánh giá.