2011-11-04 12 views
6

Ho passato molto tempo a cercare questo, per favore fatemi sapere se duplicato.SQL: Raggruppa per numero (*) come numero totale di righe di tabella

Ho bisogno di scrivere una query raggruppata che restituisca le categorie di record con il conteggio di ciascun tipo di categoria. Qualcosa del genere:

select categorynum, count(*) from tbl group by categorynum; 

Fin qui tutto bene. Ora ciò di cui ho bisogno è determinare quale percentuale del totale dei conteggi di ogni categoria occupi. Il migliore che ho venire in mente è questa, che non mi piace, ci si sente sporca:

select categorynum, count(*), count(*)/(select count(*) from tbl) from tbl group by categorynum; 

Funziona, ma è davvero fastidioso me a farlo in questo modo. Il database che uso è compatibile con Postgres e count(*) su un tavolo è molto veloce, quindi non c'è un enorme aumento di velocità per fare un count(*) sul tavolo, anche se mi piacerebbe scrivere meglio SQL se possibile.

Quindi c'è un modo migliore per scrivere questo? Questa è una situazione in cui mi imbatto spesso, quindi mi piacerebbe scrivere correttamente le mie domande.

risposta

5

Dal PostgreSQL supporta funzioni finestra, si potrebbe fare qualcosa di simile:

select categorynum,count,100*count/(sum(count) over())::numeric as count_pct 
from(
    select categorynum,count(1) 
    from tbl 
    group by categorynum 
)a; 
+0

Questo è più complicato dell'originale, ma funzionerà più velocemente? Questo tipo di query ha molte potenziali applicazioni, grazie per il puntatore! –

+0

Bene, se ci sono pochi valori di 'categorynum' rispetto al numero di righe in' tbl', allora la maggior parte del lavoro verrà eseguita nella subquery. Se la proporzione di 'categorynum' distinti rispetto al numero di righe in' tbl' è relativamente alta, la 'somma' potrebbe rallentare troppo. Controllerei il piano delle query tramite un 'explain' per entrambe le query. E tu sei il benvenuto :) –

1

È anche possibile fare il conteggio (*) sul tavolo come una query separata e poi unirsi a quella con la query originale nel Da parte della tua istruzione SELECT. Questo dovrebbe essere più veloce di metterlo nella parte SELECT.

select categorynum, categorycount, total 
from (select categorynum, count(*) as categorycount 
     from tbl 
     group by categorynum) categories, 
    (select count(*) as total from tbl) totals 
+0

Grazie, questa era l'unica opzione che avevo prima ... Il fatto è che questa tabella riceve sempre dati aggiunti, e preferirei avere una singola query piuttosto che dover eseguire due query e poi digitare i numeri in una calcolatrice/foglio di calcolo per ottenere le percentuali. –

+0

Penso che il rispondente avesse una sola domanda in mente ... scriverò un suggerimento nella risposta dove sarà leggibile. – araqnid

+0

sebbene l'esempio appena aggiunto non sia più efficiente del tuo esempio nella domanda, entrambi risultano in due scansioni complete del tavolo. ah bene, queste cose sono davvero imparate solo provandole. – araqnid

Problemi correlati