2011-11-04 123 views
6

He pasado mucho tiempo buscando esto, por favor, avíseme si es duplicado.SQL: Agrupar por recuento (*) como porcentaje del total de filas de la tabla

Necesito escribir una consulta agrupada que devuelva las categorías de registros con el recuento de cada tipo de categoría. Algo como esto:

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

Hasta ahora todo bien. Ahora lo que necesito es determinar qué porcentaje del total del recuento de cada categoría ocupa. El mejor que he llegado con esto es que no me gusta, se siente sucia:

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

Funciona, pero en realidad me molesta hacerlo de esta manera. La base de datos que uso es compatible con la sintaxis de Postgres, y count(*) en una tabla es muy rápido, por lo que no hay una gran velocidad para hacer un count(*) sobre la mesa, aunque me gustaría escribir un mejor SQL si es posible.

¿Hay alguna forma mejor de escribir esto? Esta es una situación con la que me encuentro a menudo, así que me gustaría escribir mis consultas correctamente.

Respuesta

5

Desde PostgreSQL soporta funciones de la ventana, se podría hacer algo como esto:

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

Esto es más complicado que el original, pero ¿funcionaría más rápido? Este tipo de consulta tiene muchas aplicaciones potenciales, ¡gracias por el puntero! –

+0

Bueno, si hay pocos valores de 'categorynum' relativos al número de filas en' tbl', la mayor parte del trabajo se realizará en la subconsulta. Si la proporción de distintos 'categorynums' relativos al número de filas en' tbl' es relativamente alta, entonces la 'suma' puede ralentizar demasiado. Verificaría el plan de consulta a través de una 'explicación' para ambas consultas. Y eres bienvenido. :) –

1

También se puede hacer el conteo (*) sobre la mesa como una consulta independiente y luego unirse a eso con su búsqueda original en el FROM parte de su instrucción SELECT. Eso debería ser más rápido que ponerlo en la parte SELECCIONAR.

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

Gracias, esa era la única opción que tenía antes ... La cuestión es que esta tabla siempre está recibiendo datos agregados a ella, y también preferiría tener una sola consulta que tener que ejecutar dos consultas y luego escribir los números en una calculadora/hoja de cálculo para obtener los porcentajes. –

+0

Creo que el contestador tenía una sola consulta en mente ... Escribiré una sugerencia en la respuesta donde sea legible. – araqnid

+0

aunque el ejemplo que acabo de agregar no es más eficiente que su ejemplo en la pregunta, ambos dan como resultado dos escaneos completos de la tabla. Ah, bueno, estas cosas solo se aprenden realmente al probarlas. – araqnid

Cuestiones relacionadas