PostgreSQL utilizzando count () per determinare le percentuali (problemi di trasmissione)


19

Sto cercando di eseguire la seguente query per fornire la% di righe nella mia patientstabella che hanno un valore nella refinstcolonna. Continuo a ottenere un risultato pari a 0.

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

La tabella ha 15556 righe e select count(refinst) from patientsmi dice che 1446 di questi hanno un valore nella refinstcolonna. La risposta che vorrei ottenere dalla query sarebbe 30.62 ( 1446/15556*100=30.62XXXXX, arrotondata a due decimali).

Sono abbastanza sicuro che abbia qualcosa a che fare con il tipo di dati dei risultati del conteggio (numeri interi presumo). Se divido un numero intero per un numero intero e il risultato è inferiore a 0, viene troncato a 0 corretto? In tal caso, qualcuno può mostrarmi come eseguire il cast dei risultati dei conteggi come un numero con 2 cifre decimali in modo che il risultato venga arrotondato anche a 2 cifre decimali?

Sono sicuro che esiste un modo migliore per scrivere questo codice rispetto a più istruzioni count. Sto cercando un modo più efficiente per il processore di scrivere questa query in particolare.


Forse questa risposta può aiutarti.
Jhon Anderson Cardenas Diaz,

Risposte:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • Da non usare una selezione secondaria. Entrambi gli aggregati possono essere derivati ​​dalla stessa query. Più economico.

  • Inoltre, questo non vale per le funzioni della finestra, poiché si desidera calcolare un singolo risultato e non un risultato per riga.

  • Trasmetti a qualsiasi tipo numerico che supporti cifre frazionarie, come già spiegato a @a_horse .
    Dato che vuoi inserire round()due cifre frazionarie, suggerisco numeric(che è lo stesso decimaldi Postgres).
    Ma è sufficiente lanciare un valore coinvolto in un calcolo, preferibilmente il primo. Postgres si accontenta automaticamente del tipo che non perde informazioni.

  • In genere è una buona idea moltiplicarsi prima di dividere . Questo in genere riduce al minimo gli errori di arrotondamento ed è più economico.
    In questo caso, la prima moltiplicazione ( count(refinst) * 100) può essere calcolata con un'aritmetica economica ed esatta integer. Solo allora lanciamo numerice dividiamo per il prossimo integer(che non lanciamo ulteriormente).

Arrotondato a due cifre frazionarie:

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

Ovviamente hai ragione, la funzione finestra non è necessaria. Ma poi non fa davvero la differenza (a parte la leggibilità).
a_horse_with_no_name il

3

È necessario eseguire il cast di ogni numero coinvolto nella divisione in un tipo che supporti i decimali:

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

È inoltre possibile provare una funzione di finestra anziché la query secondaria scalare. Potrebbe essere più veloce:

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

0

Mi rendo conto che questo thread ha un paio d'anni ma: prova a moltiplicare per 100,0 anziché per 100 Questo dovrebbe automaticamente trasmettere il risultato come float anziché come intero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.