2012-10-02 21 views
23

que cuentan valores de varias columnas como esta:Conde varias columnas con el grupo en una consulta por

SELECT COUNT(column1),column1 FROM table GROUP BY column1 
SELECT COUNT(column2),column2 FROM table GROUP BY column2 
SELECT COUNT(column3),column3 FROM table GROUP BY column3 

Esto devuelve por ejemplo para la gama column1 (attr1 => 2000, attr2 => 3000 ...) (Cada columna tiene valores específicos y pocos). El problema es que "tabla" en mi aplicación puede ser una consulta con algunas cláusulas join y where, que puede tomar 0.1seg. Al hacer todo lo que cuenta "tabla" se calcula cada vez que no es necesario. ¿Hay alguna manera de tomar los resultados que quiero con una consulta, o "caché" de la consulta que produce la tabla? De lo contrario, creo que la desnormalización sería la única solución aquí. Y quiero los mismos resultados con las consultas anteriores. Estoy usando mysql-myisam.

+0

¿Cómo puede el número de filas difieren para cada columna en la misma tabla? – Kermit

+0

¿puedes almacenar los resultados de tu consulta en una tabla temporal? – Beth

+0

Posible duplicado de [¿Cómo obtener múltiples conteos con una consulta SQL?] (Http://stackoverflow.com/questions/12789396/how-to-get-multiple-counts-with-one-sql-query) – kdauria

Respuesta

34

Es difícil saber cómo ayudarle sin comprender el contexto/estructura de los datos, pero creo que esto podría ayudarle a:

SELECT 
    SUM(CASE WHEN column1 IS NOT NULL THEN 1 ELSE 0 END) AS column1_count 
    ,SUM(CASE WHEN column2 IS NOT NULL THEN 1 ELSE 0 END) AS column2_count 
    ,SUM(CASE WHEN column3 IS NOT NULL THEN 1 ELSE 0 END) AS column3_count 
FROM table 
+0

. Esta es una consulta muy útil, especialmente cuando se necesita contar los registros participantes. Por ejemplo, cuando necesito el recuento de usuarios que me han enviado mensajes, uso una versión ligeramente modificada de su consulta. 'SELECT DateSent, SUM (CASO CUANDO TotalMessageCount> 1 THEN 1 ELSE 0 END) UserCount' – Vicky1729

6

Una solución es envolverlo en una subconsulta

SELECT * 
FROM 
(
    SELECT COUNT(column1),column1 FROM table GROUP BY column1 
    UNION ALL 
    SELECT COUNT(column2),column2 FROM table GROUP BY column2 
    UNION ALL 
    SELECT COUNT(column3),column3 FROM table GROUP BY column3 
) s 
+0

¿Esto no "calcular" la tabla varias veces? –

+0

Tendría que calcularlo tres veces independientemente. No puede agrupar en tres campos diferentes y esperar que el sistema no tenga que volver a calcular para cada agrupación diferente. En su cara eso es imposible. Ponerlos en una sola consulta puede permitir que el sistema reutilice la vista, pero si no, investigaría los índices o, en su defecto, las tablas temporales. –

+0

Tengo índices en todas las columnas que necesitan contar. Esta consulta no está optimizada, porque la tabla debe ser una subconsulta (SELECCIONAR columna1 DE la tabla UNIR tabla2 EN ... DONDE ....) y calcula las subconsultas de nuevo. Estaba pensando en la desnormalización, por lo que no tengo uniones. Crear tablas temporales también consume un poco de tiempo. – user666

1

Usted no ha dicho qué servidor de base de datos que está utilizando, pero si tablas temporales están disponibles que puede ser el mejor enfoque.

// table is a temp table 
select ... into #table .... 
SELECT COUNT(column1),column1 FROM #table GROUP BY column1 
SELECT COUNT(column2),column2 FROM #table GROUP BY column2 
SELECT COUNT(column3),column3 FROM #table GROUP BY column3 
// drop may not be required 
drop table #table 
+0

Sí, puedo crear tablas temporales, (servidor de la comunidad mysql) pero no creo que tenga un gran mejorar el rendimiento, ya que la creación de una tabla temporal me lleva aproximadamente 1 segundo. Las consultas toman 0.1-0.2 segundos y todas juntas alrededor de 1 segundo. (¿No te refieres a CREATE TEMPORARY TABLE AS {query}?) – user666

+0

Creo en los servidores de bases de datos Sybase la sintaxis anterior (el nombre de la tabla comienza con #) crea una tabla temporal, que normalmente se almacena en la memoria. Ese no parece ser el caso para usted, lo que resulta en costoso disco de E/S. Con las tablas en memoria, si el tamaño resultante no es demasiado grande, las tablas temporales deberían ayudar –

2
select tab1.name, 
count(distinct tab2.id) as tab2_record_count 
count(distinct tab3.id) as tab3_record_count 
count(distinct tab4.id) as tab4_record_count 
from tab1 
left join tab2 on tab2.tab1_id = tab1.id 
left join tab3 on tab3.tab1_id = tab1.id 
left join tab4 on tab4.tab1_id = tab1.id 
0
SELECT SUM(Output.count),Output.attr 
FROM 
(
    SELECT COUNT(column1 ) AS count,column1 AS attr FROM tab1 GROUP BY column1 
    UNION ALL 
    SELECT COUNT(column2) AS count,column2 AS attr FROM tab1 GROUP BY column2 
    UNION ALL 
    SELECT COUNT(column3) AS count,column3 AS attr FROM tab1 GROUP BY column3) AS Output 

    GROUP BY attr 
Cuestiones relacionadas