PostgreSQL menggunakan count () untuk menentukan persentase (masalah pemeran)

19

Saya mencoba menjalankan kueri berikut untuk memberikan% baris di patientstabel saya yang memiliki nilai refinstkolom. Saya terus mendapatkan hasil 0.

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

Tabel memiliki 15556 baris, dan select count(refinst) from patientsmemberitahu saya bahwa 1446 dari mereka memiliki nilai di refinstkolom. Respons yang ingin saya dapatkan dari kueri adalah 30,62 ( 1446/15556*100=30.62XXXXX, dibulatkan menjadi dua desimal).

Saya cukup yakin ini ada hubungannya dengan tipe data dari hasil perhitungan (bilangan bulat yang saya asumsikan). Jika saya membagi integer dengan integer dan hasilnya kurang dari 0 maka terpotong menjadi 0 benar? Jika itu masalahnya, dapatkah seseorang menunjukkan kepada saya cara melemparkan hasil penghitungan sebagai angka dengan 2 tempat desimal sehingga hasilnya akan dibulatkan menjadi 2 tempat desimal juga?

Saya yakin ada cara yang lebih baik untuk menulis kode ini daripada banyak pernyataan hitungan. Saya mencari cara yang lebih efisien prosesor untuk menulis kueri ini secara khusus.

pengguna3779117
sumber
Mungkin jawaban ini dapat membantu Anda.
Jhon Anderson Cardenas Diaz

Jawaban:

26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • Jangan tidak menggunakan subselect. Kedua agregat dapat diturunkan dari kueri yang sama. Lebih murah

  • Juga, ini bukan kasus untuk fungsi jendela, karena Anda ingin menghitung satu hasil, dan bukan satu hasil per baris.

  • Lemparkan ke jenis numerik apa pun yang mendukung angka fraksional, seperti yang sudah dijelaskan @a_horse .
    Karena Anda ingin round()dua digit fraksional saya sarankan numeric(yang sama seperti decimaldi Postgres).
    Tapi itu cukup untuk memasukkan satu nilai yang terlibat dalam perhitungan, lebih disukai yang pertama. Postgres secara otomatis menerima jenis yang tidak kehilangan informasi.

  • Biasanya merupakan ide bagus untuk berkembang biak sebelum Anda membelah . Ini biasanya meminimalkan kesalahan pembulatan dan lebih murah.
    Dalam hal ini, perkalian pertama ( count(refinst) * 100) dapat dihitung dengan integeraritmatika murah dan tepat . Hanya kemudian kita dilemparkan ke numericdan bagi dengan berikutnya integer(yang kita tidak melemparkan tambahan).

Dibulatkan menjadi dua digit pecahan:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;
Erwin Brandstetter
sumber
Tentu saja Anda benar, fungsi jendela tidak diperlukan. Tetapi kemudian itu tidak benar-benar membuat perbedaan (terlepas dari keterbacaan).
a_horse_with_no_name
3

Anda perlu memberikan setiap nomor yang terlibat dalam divisi ke jenis yang mendukung desimal:

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

Anda mungkin juga ingin mencoba fungsi jendela alih-alih sub-kueri skalar. Mungkin lebih cepat:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;
seekor kuda tanpa nama
sumber
0

Saya menyadari bahwa utas ini sudah berumur beberapa tahun tetapi: cobalah mengalikan dengan 100.0 daripada 100 Itu seharusnya secara otomatis menampilkan hasilnya sebagai float daripada integer.

Alan McGill
sumber