Câu hỏi này còn nhiều điều hơn bạn tưởng.
Phiên bản đơn giản
Đây là nhiều nhanh hơn và đơn giản hơn:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
Kết quả:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
Làm thế nào?
-
Bạn không cần một chức năng nào cho việc này.
-
Thay vì đếm
value_b
(mà bạn không cần bắt đầu bằng) và tính tổng, sử dụngcount(*)
cho tổng số. Nhanh hơn, đơn giản hơn. -
Điều này giả sử bạn không có
NULL
các giá trị. I E. cả hai cột đều được xác địnhNOT NULL
. Thông tin bị thiếu trong câu hỏi của bạn.
Nếu không, truy vấn ban đầu của bạn có thể không hoạt động như bạn nghĩ . Nếu bất kỳ giá trị nào là NULL, phiên bản của bạn hoàn toàn không tính hàng đó. Bạn thậm chí có thể kích động chia cho không ngoại lệ theo cách này.
Phiên bản này cũng hoạt động với NULL.count(*)
tạo ra số lượng tất cả các hàng, bất kể giá trị. -
Đây là cách bộ đếm hoạt động:
TRUE OR NULL = TRUE FALSE OR NULL = NULL
count()
bỏ qua giá trị NULL. Voilá. -
Mức độ ưu tiên của toán tử chi phối rằng
=
liên kết trướcOR
. Bạn có thể thêm dấu ngoặc đơn để làm rõ ràng hơn:count ((value_a = value_b) OR FALSE)
-
Bạn có thể làm tương tự với
count NULLIF(<expression>, FALSE)
-
Loại kết quả của
count()
làbigint
theo mặc định.
Một bộ phậnbigint / bigint
, cắt bớt chữ số phân số .
Bao gồm các chữ số phân số
Sử dụng 100.0
(với chữ số phân số) để buộc phép tính là numeric
và do đó giữ nguyên các chữ số phân số.
Bạn có thể muốn sử dụng round()
với cái này:
SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
Kết quả:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
Ngoài ra:
Tôi sử dụng value_a
thay vì valueA
. Không sử dụng các mã nhận dạng chữ hoa-thường chưa được trích dẫn trong PostgreSQL. Tôi đã thấy quá nhiều câu hỏi tuyệt vọng đến từ sự điên rồ này. Nếu bạn thắc mắc tôi đang nói về điều gì, hãy đọc chương Số nhận dạng và Từ khóa trong sách hướng dẫn.