PostgreSQL sử dụng Count () để xác định tỷ lệ phần trăm (các vấn đề truyền)


19

Tôi đang cố chạy truy vấn sau để cung cấp% số hàng trong patientsbảng có giá trị refinstcột. Tôi tiếp tục nhận được kết quả là 0.

select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;

Bảng này có 15556 hàng và select count(refinst) from patientscho tôi biết rằng 1446 trong số đó có giá trị trong refinstcột. Phản hồi tôi muốn nhận được từ truy vấn sẽ là 30,62 ( 1446/15556*100=30.62XXXXX, được làm tròn thành hai số thập phân).

Tôi khá chắc chắn rằng nó có liên quan đến kiểu dữ liệu của kết quả đếm (số nguyên tôi giả sử). Nếu tôi chia một số nguyên cho một số nguyên và kết quả nhỏ hơn 0 thì nó có bị cắt thành 0 không? Nếu đó là trường hợp, ai đó có thể chỉ cho tôi cách truyền kết quả của các số là một số có 2 chữ số thập phân để kết quả cũng được làm tròn thành 2 chữ số thập phân không?

Tôi chắc chắn có một cách tốt hơn để viết mã này hơn nhiều câu lệnh đếm. Tôi đang tìm kiếm một cách hiệu quả hơn bộ xử lý để viết truy vấn này nói riêng.


Có lẽ câu trả lời này có thể giúp bạn.
Jhon Anderson Cardenas Diaz

Câu trả lời:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • Đừng không sử dụng một subselect. Cả hai tổng hợp có thể được bắt nguồn từ cùng một truy vấn. Giá rẻ hơn.

  • Ngoài ra, đây không phải là trường hợp cho các chức năng của cửa sổ, vì bạn muốn tính một kết quả duy nhất và không phải là một kết quả trên mỗi hàng.

  • Truyền tới bất kỳ loại số nào hỗ trợ các chữ số phân số, như @a_horse đã được giải thích .
    Vì bạn muốn round()hai chữ số phân số tôi đề xuất numeric(giống như decimaltrong Postgres).
    Nhưng nó đủ để đưa ra một giá trị liên quan đến một phép tính, tốt nhất là giá trị đầu tiên. Postgres tự động giải quyết cho loại không mất thông tin.

  • Nói chung, đó là một ý tưởng tốt để nhân lên trước khi bạn chia . Điều này thường giảm thiểu các lỗi làm tròn và rẻ hơn.
    Trong trường hợp này, phép nhân đầu tiên ( count(refinst) * 100) có thể được tính toán với integersố học chính xác và rẻ tiền . Chỉ sau đó chúng tôi bỏ qua numericvà chia cho người tiếp theo integer(mà chúng tôi không bỏ thêm).

Làm tròn đến hai chữ số phân số:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;

Tất nhiên bạn đúng, chức năng cửa sổ là không cần thiết. Nhưng sau đó nó không thực sự tạo ra sự khác biệt (ngoài khả năng đọc).
a_horse_with_no_name

3

Bạn cần chuyển từng số liên quan đến phép chia thành một loại hỗ trợ số thập phân:

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

Bạn cũng có thể muốn thử một hàm cửa sổ thay vì truy vấn phụ vô hướng. Nó có thể nhanh hơn:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

0

Tôi nhận ra chủ đề này là một vài năm tuổi nhưng: thử nhân với 100.0 chứ không phải 100 Điều đó sẽ tự động truyền kết quả dưới dạng float chứ không phải là số nguyên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.