En SQL, quelle est la différence entre count (colonne) et count (*)?

205

J'ai la requête suivante:

select column_name, count(column_name)
from table
group by column_name
having count(column_name) > 1;

Quelle serait la différence si je remplaçais tous les appels count(column_name)vers count(*)?

Cette question a été inspirée par Comment trouver des valeurs en double dans une table dans Oracle? .


Pour clarifier la réponse acceptée (et peut-être ma question), le remplacer count(column_name)par count(*)retournerait une ligne supplémentaire dans le résultat qui contient a nullet le nombre de nullvaleurs dans la colonne.

Bill le lézard
la source

Réponses:

235

count(*)compte les valeurs NULL et count(column)ne

[modifier] a ajouté ce code pour que les gens puissent l'exécuter

create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)

select count(*),count(id),count(id2)
from #bla

résultats 7 3 2

SQLMenace
la source
8
Juste curieux: si vous avez une ligne avec tous les NULL, compterait-il (*) le compterait-il toujours, ou est-ce que compter (colonne) pour toutes les colonnes?
Joel Coehoorn
7
Est-ce standard sur tous les SGBD?
Eclipse
51
Il convient de mentionner que si vous avez une colonne non nullable telle que ID, alors count (ID) améliorera considérablement les performances par rapport au nombre (*).
tsilb
12
@tsilb: La réponse publiée par @Alan indique que "count (*) est calculé en regardant les index sur la table en question plutôt que les lignes de données réelles" qui, si elles sont vraies, invalident votre commentaire. J'apprécie que @Alan puisse être faux, mais je suis intéressé par la source de vos informations afin de savoir laquelle est correcte.
Tony
12
@tsilb: de nombreux optimiseurs de requêtes modernes optimisent le nombre (*) pour utiliser les index lorsque cela est logique.
Shannon Severance
37

Une autre différence mineure, entre l'utilisation de * et une colonne spécifique, est que dans le cas de la colonne, vous pouvez ajouter le mot clé DISTINCT et restreindre le nombre à des valeurs distinctes:

select column_a, count(distinct column_b)
from table
group by column_a
having count(distinct column_b) > 1;
Brannon
la source
1
Le groupe par colonne et celui compté devraient-ils être différents? sinon vous n'obtiendrez rien de cette requête
steevc
Oui, désolé .. Je n'avais pas remarqué qu'il s'agissait de la même colonne dans l'exemple. Je mettrai à jour le message.
Brannon
16

Une autre différence, peut-être subtile, est que dans certaines implémentations de base de données, le nombre (*) est calculé en regardant les index sur la table en question plutôt que les lignes de données réelles. Puisqu'aucune colonne spécifique n'est spécifiée, il n'est pas nécessaire de se préoccuper des lignes réelles et de leurs valeurs (comme ce serait le cas si vous comptiez une colonne spécifique). Autoriser la base de données à utiliser les données d'index peut être beaucoup plus rapide que de lui faire compter des lignes "réelles".

Alan
la source
5
+1 Oui, certainement vrai pour Oracle et pour PostgreSQL à partir de 9.2.
David Aldridge
@DavidAldridge Pouvez-vous fournir un pointeur vers la documentation (en particulier pour postgresql) où cela est mentionné? Merci.
Bhushan
@Bhushan, c'est parti wiki.postgresql.org/wiki/Index-only_scans
David Aldridge
10

L'explication dans la documentation , aide à expliquer ceci:

COUNT (*) renvoie le nombre d'éléments dans un groupe, y compris les valeurs NULL et les doublons.

COUNT (expression) évalue l'expression pour chaque ligne d'un groupe et renvoie le nombre de valeurs non nulles.

Donc, count (*) inclut des valeurs nulles, l'autre méthode ne le fait pas.

Peter C
la source
Pour les newbs SQL: à quel fichier d'aide faites-vous référence?
Bill the Lizard
10

Nous pouvons utiliser l' explorateur de données Exchange Stack pour illustrer la différence avec une simple requête. La table Utilisateurs de la base de données de Stack Overflow contient des colonnes qui sont souvent laissées vides, comme l'URL du site Web de l'utilisateur.

-- count(column_name) vs. count(*)
-- Illustrates the difference between counting a column
-- that can hold null values, a  'not null' column, and  count(*)

select count(WebsiteUrl), count(Id), count(*) from Users

Si vous exécutez la requête ci-dessus dans l' explorateur de données , vous verrez que le nombre est le même pour count(Id)et count(*)parce que la Idcolonne n'autorise pas les nullvaleurs. Le WebsiteUrlnombre est cependant beaucoup plus faible, car cette colonne le permet null.

Bill le lézard
la source
2

Fondamentalement, la COUNT(*)fonction renvoie toutes les lignes d'une table alors que ce COUNT(COLUMN_NAME)n'est pas le cas; c'est-à-dire qu'il exclut les valeurs nulles auxquelles tout le monde ici a également répondu ici. Mais la partie la plus intéressante est de rendre les requêtes et la base de données optimisées, il est préférable de les utiliser à COUNT(*)moins de faire plusieurs comptes ou une requête complexe plutôt que COUNT(COLUMN_NAME). Sinon, cela réduira vraiment les performances de votre base de données tout en traitant un grand nombre de données.

Ahmedul Kabir
la source
1
  • La phrase COUNT (*) indique à SQL Server de renvoyer toutes les lignes d'une table, y compris les valeurs NULL.
  • COUNT (nom_colonne) récupère simplement les lignes ayant une valeur non nulle sur les lignes.

Veuillez consulter le code suivant pour les exécutions de test SQL Server 2008:

-- Variable table
DECLARE @Table TABLE
(
      CustomerId int NULL 
    , Name nvarchar(50) NULL
)

-- Insert some records for tests
INSERT INTO @Table VALUES( NULL, 'Pedro')
INSERT INTO @Table VALUES( 1, 'Juan')
INSERT INTO @Table VALUES( 2, 'Pablo')
INSERT INTO @Table VALUES( 3, 'Marcelo')
INSERT INTO @Table VALUES( NULL, 'Leonardo')
INSERT INTO @Table VALUES( 4, 'Ignacio')

-- Get all the collumns by indicating *
SELECT  COUNT(*) AS 'AllRowsCount'
FROM    @Table

-- Get only content columns ( exluce NULLs )
SELECT  COUNT(CustomerId) AS 'OnlyNotNullCounts'
FROM    @Table
G21
la source
1

COUNT(*) - Renvoie le nombre total d'enregistrements dans une table (y compris les enregistrements de valeur NULL).

COUNT(Column Name) - Renvoie le nombre total d'enregistrements non NULL. Cela signifie que, il ignore le comptage des enregistrements de valeur NULL dans cette colonne particulière.

Arun Solomon
la source
0

Il est préférable d'utiliser

Count(1) in place of column name or * 

pour compter le nombre de lignes dans une table, c'est plus rapide que n'importe quel format car il ne va jamais vérifier que le nom de la colonne dans la table existe ou non

Ali Adravi
la source
4
Incorrect pour Oracle au moins, et pour les autres SGBDR aussi je soupçonne. En interne, count (1) est transformé en count (*). En particulier, les performances de count (*) ne sont pas affectées par la taille des lignes, ce qui est une idée fausse courante.
David Aldridge
Cela est vrai pour SQL Server. Comme l'a dit @Ali Adravi, COUNT(*)en comparaison avec COUNT(columnName)ne va pas vérifier la valeur des colonnes, car il énumère simplement les lignes. Mais COUNT(columnName)est plus lent, même countappliqué sur une idcolonne! Au moins dans SQL Server, bien sûr.
ABS
0

Il n'y a pas de différence si une colonne est fixe dans votre table, si vous souhaitez utiliser plus d'une colonne que vous devez spécifier le nombre de colonnes dont vous avez besoin pour compter ......

Merci,

Hiren gardhariya
la source
0

Comme mentionné dans les réponses précédentes, Count(*)compte même les NULLcolonnes, alors qu'il count(Columnname)ne compte que si la colonne a des valeurs.

Il est toujours préférable d'éviter tout *( Select *, count *, ...)

Unna
la source
Ce n'est pas du tout une bonne pratique à éviterCOUNT(*)
David Faber