Contar o número de registros retornados por grupo por

138

Como posso contar o número de registros retornados por um grupo por consulta,

Por exemplo:

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

Me dá,

1
1
2

Preciso contar os registros acima para obter 1 + 1 + 1 = 3.

Chris
fonte
3
@ LorenVS: Mas isso me daria uma contagem do número de registros na tabela. Preciso de um número de registros depois que o grupo acontece.
28411 Chris
3
O grupo por não altera o número de linhas. 1 + 1 + 2 (no seu exemplo) será o número de linhas na tabela. Você está procurando 3? O número de grupos distintos?
LorenVS
2
Outra maneira de formular a pergunta: como seleciono o número de níveis de agrupamento distintos para uma determinada consulta?
Julian
Nem sempre é óbvio o motivo pelo qual um usuário faz uma pergunta, mas cheguei aqui porque estou testando se uma coluna em uma exibição é uma chave primária candidata ou combinada. "selecionar contagem (COLUMNNAME distinto) de VIEWNAME", onde agrupar por trabalhos se eu puder obter um total.
precisa saber é o seguinte

Respostas:

169

Você pode fazer as duas coisas em uma consulta usando a cláusula OVER em outra COUNT

select
    count(*) RecordsPerGroup,
    COUNT(*) OVER () AS TotalRecords
from temptable
group by column_1, column_2, column_3, column_4
gbn
fonte
Sei que essa é uma pergunta do SQL Server, mas para referência: isso não funciona no DB / 2 (no meu caso no IBM iSeries). Veja meu comentário na resposta de
Thomas
Como eu ecoaria esse número contado?
McDan Garrett
1
O lado negativo desta solução é que ela fornece a resposta várias vezes (para cada combinação de column_1, column_2, column_3, column_4). Isso pode ou não ser um efeito colateral significativo, dependendo de como você processa os resultados.
cartbeforehorse
3
Para retornar apenas o número de registros, adicionar um select top (1) count (*) sobre () como ....
Guilherme Campos Hazan
2
No meu caso, usando TOP (1) COUNT ( ) OVER () teve um desempenho ruim da consulta. Como eu só precisava da contagem dos grupos, alterei isso para DISTINCT COUNT ( ) OVER (), e o desempenho da consulta melhorou drasticamente.
Joe Aldrich
71

A solução mais simples é usar uma tabela derivada:

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

Outra solução é usar um 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
fonte
A primeira resposta também funciona em DB / 2, mas por alguma razão ele precisa da adição AS TMP ao trabalho (como troutinator adicionado)
Bjinse
5
@Bjinse - Alguns DBMS exigirão que todas as tabelas derivadas tenham um alias. Todos aceitarão, para não machucar incluí-lo. Vou adicioná-lo à minha resposta.
Thomas
25

Eu sei que é tarde demais, mas ninguém sugeriu isso:

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

Isso funciona pelo menos no Oracle - atualmente não tenho outros bancos de dados para testá-lo e não estou tão familiarizado com a sintaxe T-Sql e MySQL.

Além disso, não tenho muita certeza se é mais eficiente no analisador fazê-lo dessa maneira ou se a solução de todos os outros de aninhar a instrução select é melhor. Mas acho que este é mais elegante do ponto de vista da codificação.

cartbeforehorse
fonte
Thomas adicionou sua solução à sua resposta. De qualquer forma. Eu não recomendaria fazer isso por motivos de manutenção, as outras soluções são muito melhores.
Răzvan Flavius ​​Panda
@ RăzvanFlaviusPanda 1. Por quê? O que há de melhor nas outras soluções? Aninhar SQL é mais detalhado e, aos meus olhos, mais confuso e mais difícil de entender (portanto, mais difícil de manter em um sentido de suporte). Entendo que você pode ter uma preferência pelas outras maneiras, mas essa não é uma razão para "recomendá-la" à preferência de outra pessoa. Thomas fez uma sugestão semelhante, sim, mas novamente ele faz parecer que aninhar o SQL é uma parte necessária da solução, o que não é.
cartbeforehorse
12

Eu estava tentando conseguir o mesmo sem subconsulta e consegui obter o resultado necessário, conforme abaixo

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

Um CTE trabalhou para mim:

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

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

E se:

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

Você poderia fazer:

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
fonte
1

No PostgreSQL, isso funciona para mim:

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

Você pode executar o seguinte código abaixo. Funcionou no Oracle.

SELECT COUNT(COUNT(*))
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Arif
fonte
1
Não é possível executar o agregado dentro de um agregado no sql-server.
A. Greensmith
0

você também pode obter a consulta abaixo

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
fonte
0

Tente esta consulta:

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

A seguir, para PrestoDb , onde o FirstField pode ter vários 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
fonte
-1

Que tal usar uma função de particionamento COUNT OVER (PARTITION BY {coluna para agrupar por}) no SQL Server?

Por exemplo, se você deseja agrupar as vendas de produtos por ItemID e deseja uma contagem de cada ItemID distinto, basta usar:

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

Se você usar essa abordagem, poderá deixar o GROUP BY fora de cena - supondo que você queira retornar a lista inteira (como você pode reportar faixas onde você precisa saber toda a contagem de itens que você vai agrupar sem ter para exibir todo o conjunto de dados, ou seja, Reporting Services).

Johnny B
fonte
Qual valor BandedItemCountconterá exatamente? Difere entre as linhas de saída? O solicitante está procurando o número de níveis de agrupamento distintos.
Julian