Contar el número de registros devueltos por grupo por

138

¿Cómo cuento el número de registros devueltos por un grupo por consulta,

Por ejemplo:

select count(*) 
from temptable
group by column_1, column_2, column_3, column_4

Me da

1
1
2

Necesito contar los registros anteriores para obtener 1 + 1 + 1 = 3.

Chris
fuente
3
@LorenVS: Pero eso me daría una cuenta del número de registros en la tabla. Necesito varios registros después de que el grupo pase.
Chris
3
Sin embargo, el grupo por no cambia el número de filas. 1 + 1 + 2 (en su ejemplo) será el número de filas en la tabla. ¿Estás buscando 3? ¿El número de grupos distintos?
LorenVS
2
Otra forma de formular la pregunta: ¿cómo selecciono el número de niveles de agrupación distintos para una consulta determinada?
Julian
No siempre es obvio por qué un usuario hace una pregunta, pero llegué aquí porque estoy probando si una columna en una vista es una clave principal o combinación de teclas candidatas. "seleccionar recuento (COLUMNNAME distinto) de VIEWNAME" agota el tiempo de espera, donde group by funciona si puedo obtener un total.
Ken Forslund

Respuestas:

170

Puede hacer ambas cosas en una consulta utilizando la cláusula OVER en otro COUNT

select
    count(*) RecordsPerGroup,
    COUNT(*) OVER () AS TotalRecords
from temptable
group by column_1, column_2, column_3, column_4
gbn
fuente
Sé que esta es una pregunta de SQL Server, pero como referencia: esto no funciona en DB / 2 (en mi caso en IBM iSeries). Ver mi comentario en la respuesta de
Thomas
¿Cómo haría eco de ese número contado?
McDan Garrett
1
El inconveniente de esta solución es que le da la respuesta varias veces (para cada combinación de column_1, column_2, column_3, column_4). Esto puede o no ser un efecto secundario significativo, dependiendo de cómo procese los resultados.
cartbeforehorse
3
Para devolver solo el número de registros, agregue un recuento de selección superior (1) (*) sobre () como ...
Guilherme Campos Hazan
2
En mi caso, el uso de TOP (1) COUNT ( ) OVER () tuvo un rendimiento de consulta deficiente. Como solo necesitaba el recuento de los grupos, cambié esto a DISTINCT COUNT ( ) OVER (), y el rendimiento de la consulta mejoró drásticamente.
Joe Aldrich
71

La solución más simple es usar una tabla derivada:

Select Count(*)
From    (
        Select ...
        From TempTable
        Group By column_1, column_2, column_3, column_4
        ) As Z

Otra solución es usar un Count Distinct:

Select ...
    , ( Select Count( Distinct column_1, column_2, column_3, column_4 )
        From TempTable ) As CountOfItems
From TempTable
Group By column_1, column_2, column_3, column_4
Thomas
fuente
La primera respuesta también funciona en DB / 2, pero por alguna razón necesita la adición de AS TMP para funcionar (como se agregó troutinator)
Bjinse
55
@Bjinse: algunos DBMS requerirán que todas las tablas derivadas tengan un alias. Todos lo aceptarán para que no esté de más incluirlo. Lo agregaré a mi respuesta.
Thomas
25

Sé que es bastante tarde, pero nadie ha sugerido esto:

select count ( distinct column_1, column_2, column_3, column_4) 
from   temptable

Esto funciona al menos en Oracle: actualmente no tengo otras bases de datos para probarlo, y no estoy tan familiarizado con la sintaxis de T-Sql y MySQL.

Además, no estoy completamente seguro de si es más eficiente en el analizador hacerlo de esta manera, o si la solución de todos los demás de anidar la instrucción select es mejor. Pero creo que este es más elegante desde una perspectiva de codificación.

cartbeforehorse
fuente
Thomas agregó su solución a su respuesta. De todas formas. No recomendaría hacer esto por razones de mantenimiento, las otras soluciones son mucho mejores.
Răzvan Flavius ​​Panda
@ RăzvanFlaviusPanda 1. ¿Por qué? ¿Qué hay de bueno en las otras soluciones? Anidar SQL es más detallado y, en mi opinión, más desordenado y más difícil de entender (ergo más difícil de mantener en un sentido de soporte). Entiendo que puede tener una preferencia por las otras formas, pero esa no es una razón para "recomendar" sobre la preferencia de otra persona. Thomas hizo una sugerencia similar, sí, pero nuevamente hace que parezca que anidar el SQL es una parte necesaria de la solución, que no lo es.
cartbeforehorse
12

Estaba tratando de lograr lo mismo sin consultar y pude obtener el resultado requerido de la siguiente manera

SELECT DISTINCT COUNT(*) OVER () AS TotalRecords
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Manish Mulani
fuente
4

Un CTE funcionó para mí:

with cte as (
  select 1 col1
  from temptable
  group by column_1
)

select COUNT(col1)
from cte;
SQL Pete
fuente
3

Qué tal si:

SELECT count(column_1)
FROM
    (SELECT * FROM temptable
    GROUP BY column_1, column_2, column_3, column_4) AS Records
PedroC88
fuente
1

Podrías hacerlo:

select sum(counts) total_records from (
    select count(*) as counts
    from temptable
    group by column_1, column_2, column_3, column_4
) as tmp
troutinator
fuente
1

En PostgreSQL esto funciona para mí:

select count(count.counts) 
from 
    (select count(*) as counts 
     from table 
     group by concept) as count;
omar
fuente
1

¿Puedes ejecutar el siguiente código a continuación? Funcionó en Oracle.

SELECT COUNT(COUNT(*))
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Arif
fuente
1
No se puede ejecutar agregado dentro de un agregado en sql-server.
A. Greensmith
0

También puede obtener la siguiente consulta

select column_group_by,count(*) as Coulm_name_to_be_displayed from Table group by Column;

-- For example:
select city,count(*) AS Count from people group by city
Nitish Sahoo
fuente
0

Prueba esta consulta:

select top 1 TotalRows = count(*) over () 
from yourTable
group by column1, column2
Marimuthu Shanmugasundaram
fuente
0

Siguiente para PrestoDb , donde FirstField puede tener múltiples valores:

select *
            , concat(cast(cast((ThirdTable.Total_Records_in_Group * 100 / ThirdTable.Total_Records_in_baseTable) as DECIMAL(5,2)) as varchar), '%') PERCENTage
from 
(
    SELECT FirstTable.FirstField, FirstTable.SecondField, SecondTable.Total_Records_in_baseTable, count(*) Total_Records_in_Group
    FROM BaseTable FirstTable
    JOIN (
            SELECT FK1, count(*) AS Total_Records_in_baseTable 
            FROM BaseTable
            GROUP BY FK1
        ) SecondTable
    ON FirstTable.FirstField = SecondTable.FK1
    GROUP BY FirstTable.FirstField, FirstTable.SecondField, SecondTable.Total_Records_in_baseTable
    ORDER BY FirstTable.FirstField, FirstTable.SecondField
) ThirdTable
SUKUMAR S
fuente
-1

¿Qué tal usar una función de partición COUNT OVER (PARTITION BY {column to group by}) en SQL Server?

Por ejemplo, si desea agrupar las ventas de productos por ItemID y desea un recuento de cada ItemID distinto, simplemente use:

SELECT
{columns you want} ,
COUNT(ItemID) OVER (PARTITION BY ItemID) as BandedItemCount ,
{more columns you want}... ,
FROM {MyTable}

Si usa este enfoque, puede dejar el GROUP BY fuera de la imagen, suponiendo que desea devolver la lista completa (ya que podría informar las bandas donde necesita saber el recuento completo de elementos que va a agrupar sin tener para mostrar todo el conjunto de datos, es decir, Reporting Services).

Johnny B
fuente
¿Qué valor BandedItemCountcontendrá exactamente? ¿Difiere entre las filas de salida? El autor de la pregunta busca el número de niveles de agrupación distintos.
Julian