sql >> Base de Datos >  >> RDS >> PostgreSQL

Calcule porcentajes de SUM () en la misma consulta SELECT sql

Hay más en esta pregunta de lo que parece.

Versión sencilla

Esto es mucho más rápido y sencillo:

SELECT property_name
      ,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM   my_obj
GROUP  BY 1;

Resultado:

property_name | pct
--------------+----
 prop_1       | 17
 prop_2       | 43

¿Cómo?

  • No necesitas una función para esto en absoluto.

  • En lugar de contar value_b (que no necesita para empezar) y calculando el total, use count(*) para el total. Más rápido, más simple.

  • Esto supone que no tiene NULL valores. Es decir. ambas columnas están definidas NOT NULL . Falta información en su pregunta.
    Si no es así, su consulta original probablemente no está haciendo lo que cree que hace . Si alguno de los valores es NULL, su versión no cuenta esa fila en absoluto. Incluso podría provocar una división por cero excepción de esta manera.
    Esta versión también funciona con NULL. count(*) produce el recuento de todas las filas, independientemente de los valores.

  • Así es como funciona el conteo:

     TRUE  OR NULL = TRUE
     FALSE OR NULL = NULL
    

    count() ignora los valores NULL. Voilá.

  • La precedencia de operadores gobierna que = se une antes de OR . Puede agregar paréntesis para que quede más claro:

    count ((value_a = value_b) OR FALSE)
    
  • Puedes hacer lo mismo con

    count NULLIF(<expression>, FALSE)
    
  • El tipo de resultado de count() es bigint por defecto.
    Una división bigint / bigint , trunca dígitos fraccionarios .

Incluye dígitos fraccionarios

Usa 100.0 (con dígito fraccionario) para forzar que el cálculo sea numeric y por lo tanto preservar los dígitos fraccionarios.
Es posible que desee utilizar round() con esto:

SELECT property_name
      ,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM   my_obj
GROUP  BY 1;

Resultado:

property_name | pct
--------------+-------
 prop_1       | 17.23
 prop_2       | 43.09

Aparte:
Uso value_a en lugar de valueA . No utilice identificadores de mayúsculas y minúsculas sin comillas en PostgreSQL. He visto demasiadas preguntas desesperadas provenientes de esta locura. Si se pregunta de qué estoy hablando, lea el capítulo Identificadores y palabras clave del manual.