PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Calcola le percentuali da SUM() nella stessa query SELECT sql

C'è di più in questa domanda di quanto possa sembrare.

Versione semplice

Questo è molto più veloce e più semplice:

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

Risultato:

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

Come?

  • Non hai affatto bisogno di una funzione per questo.

  • Invece di contare value_b (con cui non è necessario iniziare) e calcolando il totale, usa count(*) per il totale. Più veloce, più semplice.

  • Ciò presuppone che tu non abbia NULL valori. Cioè. entrambe le colonne sono definite NOT NULL . Le informazioni mancano nella tua domanda.
    In caso negativo, la tua query originale probabilmente non sta facendo ciò che pensi . Se uno qualsiasi dei valori è NULL, la tua versione non conta affatto quella riga. Potresti anche provocare una divisione per zero eccezione in questo modo.
    Questa versione funziona anche con NULL. count(*) produce il conteggio di tutte le righe, indipendentemente dai valori.

  • Ecco come funziona il conteggio:

     TRUE  OR NULL = TRUE
     FALSE OR NULL = NULL
    

    count() ignora i valori NULL. Voilà.

  • La precedenza dell'operatore regola quel = si lega prima di OR . Potresti aggiungere parentesi per renderlo più chiaro:

    count ((value_a = value_b) OR FALSE)
    
  • Puoi fare lo stesso con

    count NULLIF(<expression>, FALSE)
    
  • Il tipo di risultato di count() è bigint per impostazione predefinita.
    Una divisione bigint / bigint , tronca le cifre frazionarie .

Includi cifre frazionarie

Usa 100.0 (con cifra frazionaria) per forzare il calcolo a essere numeric e quindi preservare le cifre frazionarie.
Puoi utilizzare round() con questo:

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

Risultato:

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

Per inciso:
io uso value_a invece di valueA . Non utilizzare identificatori di maiuscole e minuscole non quotate in PostgreSQL. Ho visto troppe domande disperate provenire da questa follia. Se ti chiedi di cosa sto parlando, leggi il capitolo Identificatori e parole chiave del manuale.