PostgreSQL usando count () para determinar porcentajes (problemas de conversión)


19

Estoy tratando de ejecutar la siguiente consulta para proporcionar el% de filas en mi patientstabla que tienen un valor en la refinstcolumna. Sigo obteniendo un resultado de 0.

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

La tabla tiene 15556 filas y select count(refinst) from patientsme dice que 1446 de ellas tienen un valor en la refinstcolumna. La respuesta que me gustaría obtener de la consulta sería 30.62 ( 1446/15556*100=30.62XXXXXredondeada a dos decimales).

Estoy bastante seguro de que tiene algo que ver con el tipo de datos de los resultados del recuento (supongo que enteros). Si divido un entero por un entero y el resultado es menor que 0, ¿se trunca a 0 correcto? Si ese es el caso, ¿alguien puede mostrarme cómo convertir los resultados de los recuentos como un número con 2 decimales para que el resultado también se redondee a 2 decimales?

Estoy seguro de que hay una mejor manera de escribir este código que las declaraciones de recuento múltiple. Estoy buscando una forma más eficiente de procesador para escribir esta consulta en particular.


Quizás esta respuesta pueda ayudarte.
Jhon Anderson Cardenas Diaz

Respuestas:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • No , no utilizar una subselección. Ambos agregados pueden derivarse de la misma consulta. Más barato

  • Además, este no es un caso para las funciones de ventana, ya que desea calcular un solo resultado, y no un resultado por fila.

  • Convierta a cualquier tipo numérico que admita dígitos fraccionarios, como @a_horse ya explicado .
    Como desea tener round()dos dígitos fraccionarios, sugiero numeric(que es lo mismo que decimalen Postgres).
    Pero es suficiente para emitir un valor involucrado en un cálculo, preferiblemente el primero. Postgres se conforma automáticamente con el tipo que no pierde información.

  • Generalmente es una buena idea multiplicar antes de dividir . Esto generalmente minimiza los errores de redondeo y es más barato.
    En este caso, la primera multiplicación ( count(refinst) * 100) se puede calcular con integeraritmética barata y exacta . Sólo entonces echamos a numericy se divide por la siguiente integer(que nosotros no echamos adicionalmente).

Redondeado a dos dígitos fraccionarios:

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

Por supuesto que tiene razón, la función de ventana no es necesaria. Pero entonces realmente no hace la diferencia (aparte de la legibilidad).
a_horse_with_no_name

3

Debe convertir cada número involucrado en la división a un tipo que admita decimales:

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

También es posible que desee probar una función de ventana en lugar de la subconsulta escalar. Podría ser más rápido:

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

0

Me doy cuenta de que este hilo tiene un par de años, pero: intente multiplicarlo por 100.0 en lugar de por 100 Eso debería arrojar automáticamente el resultado como un flotante en lugar de un entero.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.