Retour à la liste des articles Articles
10 minutes de lecture

Quelle est la différence entre COUNT(*), COUNT(1), COUNT(nom de la colonne) et COUNT(DISTINCT nom de la colonne) ?

Avez-vous remarqué qu'il existe différentes variantes de la fonction SQL COUNT() ? Cet article explique les différents arguments et leurs utilisations.

En tant qu'utilisateur de SQL, vous êtes probablement assez familier avec la fonction COUNT(). Même si elle est relativement simple, elle peut être utilisée de plusieurs façons différentes. Chaque façon a une utilisation très différente. J'imagine que vous avez déjà vu du code contenant la fonction COUNT(*) ou COUNT(1). Vous avez probablement aussi vu d'autres utilisations de la fonction COUNT(), comme COUNT(nom_colonne) et COUNT(DISTINCT nom_colonne), même si vous ne les avez pas utilisées.

Vous vous demandez probablement ce que fait chaque variation de COUNT(). Nous allons le découvrir !

Avant de poursuivre, je tiens à préciser que j'utiliserai la fonction GROUP BY dans cet article, mais uniquement de manière très simple. Si vous avez besoin de vous rafraîchir la mémoire sur GROUP BY, voici un article qui vous guidera à travers la syntaxe et les principes généraux de GROUP BY. Vous pouvez également apprendre les principes fondamentaux de GROUP BY dans notre cours interactif SQL pour les débutants. Il contient plus de 100 exercices SQL pratiques pour renforcer votre confiance en vos compétences SQL au fur et à mesure.

Que fait la fonction COUNT() ?

Comme vous pouvez l'imaginer, la fonction COUNT() compte. Mais que compte-t-elle ? La fonction COUNT() appartient aux fonctions d'agrégation de SQL. Elle compte le nombre de lignes qui répondent aux critères définis entre parenthèses. Elle ne renvoie pas les lignes elles-mêmes ; elle indique le nombre de lignes qui répondent à vos critères.

En parlant des fonctions d'agrégation, elles sont extrêmement utiles dans les rapports SQL. Si vous voulez satisfaire votre curiosité, notre cours Création de rapports basiques en SQL traite en détail des fonctions d'agrégation et du " grouping by ".

Revenons maintenant au comptage. Il y a (naturellement) différentes choses qui peuvent être comptées. C'est pourquoi il existe différentes variantes de la fonction COUNT(). Dans cet article, je vais me concentrer sur quatre d'entre elles :

  • COUNT(*)
  • COUNT(1)
  • COUNT(nom_colonne)
  • COUNT(DISTINCT nom_colonne)

COUNT(*) vs COUNT(1)

Vous avez peut-être vu diverses discussions sur les différences entre COUNT(*) et COUNT(1). Et peut-être que le fait d'essayer de trouver la réponse vous a rendu encore plus confus. Alors, y a-t-il une différence ? La réponse est simple : il n'y a pas de différence du tout.

La fonction COUNT(*) compte le nombre total de lignes de la table, y compris les valeurs de NULL. La sémantique de COUNT(1) diffère légèrement ; nous en discuterons plus tard. Cependant, les résultats pour COUNT(*) et COUNT(1) sont identiques.

Testons cette affirmation à l'aide d'un exemple de requête. Supposons que j'ai une table nommée commandes qui contient les colonnes suivantes :

  • id_commande : L'ID de la commande.
  • id_client : L'ID du client qui a passé la commande.
  • montant_total_commande : La valeur totale des articles commandés, en euros.
  • date_paiement : La date à laquelle la commande a été payée par le client.

Si je voulais compter le nombre de lignes dans l'ensemble de la table, j'utiliserais la fonction COUNT() de la manière suivante :

SELECT COUNT(*) AS nbr_lignes
FROM commandes;

Comme vous le voyez, j'ai utilisé la fonction COUNT(*). Le résultat apparaîtra dans la nouvelle colonne nbr_lignes:

nbr_lignes
8

Ok, mais comment faire pour utiliser COUNT(1) à la place ? C'est ici :

SELECT COUNT(1) AS nbr_lignes
FROM commandes;

Le code est essentiellement le même. La seule différence est que j'ai utilisé COUNT(1) au lieu de COUNT(*). Et qu'en est-il du résultat ? Il renvoie le même nombre de lignes :

nbr_lignes
8

Il existe une idée fausse très répandue selon laquelle le " 1 " de COUNT(1) signifie "compte les valeurs de la première colonne et renvoie le nombre de lignes". De cette idée fausse découle une deuxième : que COUNT(1) est plus rapide parce qu'il ne comptera que la première colonne, alors que COUNT(*) utilisera la totalité de la table pour arriver au même résultat.

Ce n'est pas vrai. Le nombre entre parenthèses ne signifie pas le numéro de la colonne dans la table. Si vous mettez, n'importe quel nombre entre parenthèses, je vous garantis que le résultat sera le même. Vous voulez une preuve ? La voici :

SELECT COUNT(-13) AS nbr_lignes
FROM commandes;

Si la première idée fausse était vraie, le code ci-dessus signifierait que je veux compter le nombre de lignes dans la -13e colonne. Il n'y a que quatre colonnes dans la table commandes, donc il n'y a pas de 13è colonne. Pour sûr, il n'y a pas de colonne -13, quoi que cela puisse vouloir dire. Voulez-vous voir le résultat de ce code ? Ne soyez pas surpris :

nbr_lignes
8

Une fois de plus, le résultat est le même. Que signifie donc la valeur entre parenthèses de COUNT()? C'est la valeur que la fonction COUNT() va attribuer à chaque ligne de la table. La fonction comptera ensuite combien de fois l'astérisque (*) ou (1) ou (-13) a été attribué. Bien entendu, il sera affecté un nombre de fois égal au nombre de lignes de la table. En d'autres termes, COUNT(1) attribue la valeur des parenthèses (le numéro 1, dans notre cas) à chaque ligne de la table, puis la même fonction compte combien de fois la valeur entre parenthèses (1, dans notre cas) a été attribuée ; naturellement, ce nombre sera toujours égal au nombre de lignes de la table. Les parenthèses peuvent contenir n'importe quelle valeur ; la seule chose qui ne fonctionnera pas sera de laisser les parenthèses vides.

Essayons quelque chose de stupide. Au lieu d'un nombre, mettez la valeur suivante dans la parenthèse : " il y aura toujours 8 lignes ". Voici le code :

SELECT COUNT('il y a toujours 8 lignes') AS nbr_lignes
FROM commandes;

Exécutez le code et - surprise, surprise - le résultat est vraiment 8 lignes :

nbr_lignes
8

Puisque la valeur que vous mettez entre parenthèses n'a pas d'importance, il s'ensuit que COUNT(*) et COUNT(1) sont exactement les mêmes. Elles sont exactement les mêmes parce que la valeur entre les parenthèses de COUNT() sert uniquement à indiquer à la requête ce qu'elle doit compter.

Si ces déclarations sont exactement les mêmes, alors il n'y a aucune différence dans les performances. Ne laissez pas l'astérisque (*) vous faire croire qu'il a la même utilité que dans la déclaration SELECT *. Non, COUNT(*) ne parcourra pas toute la table avant de renvoyer le nombre de lignes, ce qui le rendra plus lent que COUNT(1).

En fin de compte, qui gagne dans cette bataille dramatique entre COUNT(*) et COUNT(1)? Personne - c'est un match nul ; ils sont exactement pareils. Cependant, je vous recommande d'utiliser COUNT(*), car c'est une expression plus courante. C'est également moins déroutant, car les autres utilisateurs de SQL comprendront naturellement que la fonction comptera tous les nombres de la table, y compris les valeurs NULL.

COUNT(*) vs COUNT(nom de la colonne)

Que diriez-vous de celle-là, COUNT(*) vs COUNT(nom_colonne). Y a-t-il une différence ? Bien sûr que oui !

Comme vous l'avez déjà appris, COUNT(*) comptera toutes les lignes de la table, y compris les valeurs de NULL. D'autre part, COUNT(nom_colonne) comptera toutes les lignes de la colonne spécifiée en excluant les valeurs NULL.

Comme vous le savez déjà, il y a huit lignes dans la table commandes. Voyons combien de lignes il y aura si j'utilise la colonne id_commande pour le comptage (en imaginant que je veux voir combien de commandes ont été passées). Nous aurons à nouveau huit lignes, n'est-ce pas ? Voyons voir :

SELECT COUNT(id_commande) AS nbr_commandes
FROM commandes;

On obtient le même résultat ? Non, il y a sept commandes, pas huit.

nbr_commandes
7

Est-ce une erreur ? Non, ce n'est pas une erreur ; il n'y a en fait que sept ordres avec un id_commande; une ligne a un NULL au lieu d'un id_commande correct. Vous trouverez ci-dessous la ligne qui fait la différence :

id_commandeid_clientprix_commandedate_commande
NULLCU0921327.85NULL

N'oubliez jamais : COUNT(nom_colonne) ne comptera que les lignes où la colonne donnée est NOT NULL

.

Faisons maintenant quelque chose d'intéressant et combinons les deux variantes de COUNT() en une seule requête. Supposons que je veuille voir l'ID du client avec le nombre total de commandes de ce client. Je veux également afficher le nombre total de commandes payées pour ce client. (Les commandes payées n'ont pas de valeur NULL dans la colonne payment_date.) Voici comment procéder :

SELECT	id_client,
		COUNT(*) AS nbr_commandes,
		COUNT(payment_date) AS nbr_commandes_payees
FROM commandes
GROUP BY id_client;

La requête calculera d'abord le nombre total de commandes en utilisant COUNT(*) - c'est-à-dire qu'elle inclura les valeurs de NULL. Ensuite, la partie COUNT (date_paiement) AS nbr_commandes_payees comptera les lignes de la colonne payment_date qui sont NOT NULL. Je veux les résultats pour chaque client, donc j'ai regroupé le résultat par la colonne id_client. Voici ce que j'obtiens :

id_clientnbr_commandesnbr_commandes_payees
CU01211
CU04911
CU05222
CU09210
CU10822
CU14911

Vous pouvez voir que la différence se produit pour le client CU092.

Les principes de la combinaison de GROUP BY et COUNT() sont exposés dans cet article sur le GROUP BY et les fonctions d'agrégation SQL. Si vous souhaitez vous exercer davantage, voici cinq exemples de GROUP BY.

COUNT() nous permet d'utiliser des expressions ainsi que des noms de colonnes comme argument. Savez-vous comment trouver le nombre de commandes supérieures à 1 000 € en utilisant uniquement la fonction COUNT()? Voici comment :

SELECT COUNT(CASE WHEN prix_commande > 1000 THEN 1 END) 
AS commandes_significatives
FROM commandes;

Au lieu de mettre les conditions à la fin de la requête et de filtrer après que la fonction COUNT() ait fait son travail, nous pouvons utiliser l'instruction CASE. C'est ce que j'ai fait dans la requête ci-dessus. Elle est utilisée comme une instruction IF-THEN-ELSE. CASE est suivie de la condition, qui est définie par les instructions WHEN et THEN. Il peut aussi y avoir une instruction ELSE, mais elle n'est pas nécessaire dans ce cas - je suis seulement intéressé par le nombre de valeurs, pas par les valeurs elles-mêmes. Chaque instruction CASE se termine par l'instruction END.

L'instruction COUNT() ci-dessus se lit comme suit :

  1. Trouvez toutes les valeurs supérieures à 1 000 dans la colonne prix_commande.
  2. Attribuez la valeur 1 (vous pouvez attribuer la valeur de votre choix) à ces valeurs.
  3. Attribuez la valeur NULL aux lignes dont le prix est inférieur à 1 000.
  4. Comptez le nombre de valeurs 1 attribuées.
  5. Affichez le résultat dans la colonne commandes_significatives.

Voici le résultat :

commandes_significatives
5

COUNT(nom de la colonne) vs COUNT (DISTINCT nom_colonne)

Vous pouvez probablement imaginer quelle est la différence entre ces deux versions de la fonction COUNT(). COUNT(column_name) inclura les valeurs dupliquées lors du comptage. En revanche, COUNT (DISTINCT column_name) ne comptera que les lignes distinctes (uniques) dans la colonne définie.

Si vous voulez compter le nombre de clients qui ont passé une commande, COUNT (column_name) fera peut-être l'affaire. Essayons ce code simple :

SELECT COUNT (id_client) AS nbr_clients
FROM commandes;

Celui-ci vous est familier ; j'ai déjà utilisé la fonction COUNT(nom_colonne). Cette fois, elle compte toutes les lignes de la colonne id_client, et le résultat est affiché dans la colonne nbr_clients. Voici le résultat :

nbr_clients
8

Vérifions le résultat en regardant l'ensemble de la table commandes:

id_commandeid_clientprix_commandedate_commande
OR2020-01CU108154872020-01-08
OR2020-28CU149154872020-01-14
OR2020-12CU10812549.222020-01-09
OR2020-91CU012542.55NULL
NULLCU0921327.85NULL
OR2020-112CU049150002020-02-28
OR2020-213CU0521502020-03-12
OR2020-213CU0522002020-03-12

Il y a huit lignes, mais est-ce vraiment le nombre de clients ? Remarquez que les clients CU108 et CU052 apparaissent deux fois. Si je veux connaître le nombre réel de clients, je dois compter chaque client une seule fois. Comment puis-je le faire ? En utilisant COUNT(DISTINCT id_client):

SELECT COUNT(DISTINCT id_client) AS nbr_clients
FROM commandes;

Cette requête comptera également les lignes de la colonne id_client, mais elle ne comptera chaque client qu'une seule fois. Ceci est dû au mot-clé DISTINCT. Regardez le résultat :

nbr_clients
6

C'est le bon résultat ; il n'y a en réalité que six clients uniques.

Pensez-vous que vous pouvez compter sur COUNT() ?

Maintenant, que vous comprenez plusieurs variations courantes de la fonction COUNT(), vous pouvez créer des calculs et des rapports plus complexes. COUNT() est l'une des fonctions d'agrégation les plus utilisées, il est donc essentiel que vous compreniez clairement les différentes variations de COUNT() et leurs objectifs. Si certaines des variations de la fonction COUNT() dont nous avons parlé dans cet article n'étaient pas claires, faites-le moi savoir dans la section des commentaires. Je me ferai un plaisir de vous aider. Et, pour vous entraîner davantage à utiliser COUNT(), essayez notre cours Création de rapports basiques en SQL.