Compter le nombre d'enregistrements renvoyés par groupe par

138

Comment compter le nombre d'enregistrements renvoyés par un groupe par requête,

Par exemple:

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

Donne moi,

1
1
2

Je dois compter les enregistrements ci-dessus pour obtenir 1 + 1 + 1 = 3.

Chris
la source
3
@LorenVS: Mais cela me donnerait un décompte du nombre d'enregistrements dans le tableau. J'ai besoin d'un certain nombre d'enregistrements une fois le groupe arrivé.
Chris
3
Cependant, le groupement ne change pas le nombre de lignes. 1 + 1 + 2 (dans votre exemple) sera le nombre de lignes du tableau. Cherchez-vous 3? Le nombre de groupes distincts?
LorenVS
2
Une autre façon de formuler la question: comment sélectionner le nombre de niveaux de regroupement distincts pour une requête donnée?
Julian
Il n'est pas toujours évident de savoir pourquoi un utilisateur pose une question, mais je suis arrivé ici parce que je teste si une colonne dans une vue est une clé primaire candidate ou une clé de combinaison. "select count (distinct COLUMNNAME) from VIEWNAME" expire, où le groupe par œuvres si je peux obtenir un total.
Ken Forslund

Réponses:

170

Vous pouvez faire les deux dans une requête en utilisant la clause OVER sur un autre COUNT

select
    count(*) RecordsPerGroup,
    COUNT(*) OVER () AS TotalRecords
from temptable
group by column_1, column_2, column_3, column_4
gbn
la source
Je sais que c'est une question SQL-Server, mais pour référence: cela ne fonctionne pas sur DB / 2 (dans mon cas sur IBM iSeries). Voir mon commentaire sur la réponse de
Thomas
Comment pourrais-je faire écho à ce nombre compté?
McDan Garrett
1
L'inconvénient de cette solution est qu'elle vous donne la réponse plusieurs fois (pour chaque combinaison de column_1, column_2, column_3, column_4). Cela peut être ou non un effet secondaire important, selon la façon dont vous traitez les résultats.
cartbeforehorse
3
Pour ne renvoyer que le nombre d'enregistrements, ajoutez un top (1) count (*) over () as ....
Guilherme Campos Hazan
2
Dans mon cas, l'utilisation de TOP (1) COUNT ( ) OVER () avait des performances de requête médiocres. Comme je n'avais besoin que du nombre de groupes, j'ai changé cela en DISTINCT COUNT ( ) OVER (), et les performances des requêtes se sont considérablement améliorées.
Joe Aldrich
71

La solution la plus simple consiste à utiliser une table dérivée:

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

Une autre solution consiste à utiliser 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
la source
La première réponse fonctionne également sur DB / 2, mais pour une raison quelconque, elle a besoin de l'ajout AS TMP pour fonctionner (comme l'ajout de troutinator)
Bjinse
5
@Bjinse - Certains SGBD exigeront que toutes les tables dérivées aient un alias. Ils l'accepteront tous pour ne pas faire de mal de l'inclure. Je vais l'ajouter à ma réponse.
Thomas
25

Je sais qu'il est plutôt tard, mais personne n'a suggéré ceci:

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

Cela fonctionne au moins dans Oracle - je n'ai actuellement pas d'autres bases de données sur lesquelles le tester, et je ne suis pas très familier avec la syntaxe T-Sql et MySQL.

De plus, je ne suis pas tout à fait sûr qu'il soit plus efficace dans l'analyseur de le faire de cette façon, ou si la solution de tout le monde consistant à imbriquer l'instruction select est meilleure. Mais je trouve celui-ci plus élégant du point de vue du codage.

chariot
la source
Thomas a ajouté votre solution à sa réponse. En tous cas. Je ne recommanderais jamais de faire cela pour des raisons de maintenance, les autres solutions sont beaucoup plus agréables.
Răzvan Flavius ​​Panda
@ RăzvanFlaviusPanda 1. Pourquoi? Qu'y a-t-il de plus agréable dans les autres solutions? Nesting SQL est plus verbeux et à mes yeux, plus désordonné et plus difficile à comprendre (ergo plus difficile à maintenir dans un sens de support). Je comprends que vous avez peut-être une préférence pour les autres moyens, mais ce n'est pas une raison pour le «recommander» plutôt que la préférence de quelqu'un d'autre. Thomas a fait une suggestion similaire, oui, mais encore une fois, il donne l'impression que l'imbrication du SQL est une partie nécessaire de la solution, ce qui n'est pas le cas.
cartbeforehorse
12

J'essayais d'obtenir la même chose sans sous-requête et j'ai pu obtenir le résultat requis comme ci-dessous

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

Un CTE a travaillé pour moi:

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

select COUNT(col1)
from cte;
SQL Pete
la source
3

Que diriez-vous:

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

Vous pourriez faire:

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

Dans PostgreSQL, cela fonctionne pour moi:

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

Pouvez-vous exécuter le code suivant ci-dessous. Cela a fonctionné dans Oracle.

SELECT COUNT(COUNT(*))
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Arif
la source
1
Impossible d'exécuter l'agrégat dans un agrégat sur le serveur sql.
A. Greensmith
0

vous pouvez également obtenir par la requête ci-dessous

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
la source
0

Essayez cette requête:

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

Suivant pour PrestoDb , où FirstField peut avoir plusieurs valeurs:

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
la source
-1

Que diriez-vous d'utiliser une fonction de partitionnement COUNT OVER (PARTITION BY {column to group by}) dans SQL Server?

Par exemple, si vous souhaitez regrouper les ventes de produits par ItemID et que vous voulez un nombre de chaque ItemID distinct, utilisez simplement:

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

Si vous utilisez cette approche, vous pouvez laisser le GROUP BY en dehors de l'image - en supposant que vous souhaitiez renvoyer la liste entière (comme vous pourriez le faire pour signaler le regroupement où vous devez connaître le nombre total d'éléments que vous allez regrouper sans avoir pour afficher l'ensemble des données, c'est-à-dire Reporting Services).

Johnny B
la source
Quelle valeur BandedItemCountcontiendra exactement? Cela diffère-t-il entre les lignes de sortie? Le demandeur recherche le nombre de niveaux de regroupement distincts.
Julian