À l'université, mon professeur m'a appris cette année que cette déclaration SQL:
SELECT COUNT(length) FROM product
renverra 2
avec l'ensemble de données suivant:
| product |
|id | length | code |
|-------------------|
| 1 | 11 | X00 |
| 2 | 11 | C02 |
| 3 | 40 | A31 |
Elle l'a justifié en disant que COUNT
ne compte pas les doublons.
J'ai dit à mon professeur que je pensais qu'elle avait fait une erreur. Elle m'a répondu que certains SGBD peuvent ou non compter les doublons.
Après avoir essayé beaucoup de SGBD, je n'en ai jamais trouvé un qui a ce comportement.
Ce SGBD existe-t-il?
Y a-t-il une raison pour qu'un professeur enseigne ce comportement? Et sans même mentionner que d'autres SGBD peuvent se comporter différemment?
Pour info, le support du cours est disponible ici . La diapositive concernée se trouve dans le coin inférieur gauche à la page 10.
COUNT
compte les doublons dans tous les SGBD que je connais, mais.
Y a-t-il une raison pour qu'un professeur enseigne ce comportement
Oui, il y a une raison. Dans la théorie relationnelle originale (qui sous-tend tous les SGBD relationnels modernes) la relation est un ensemble au sens mathématique de ce mot. Cela signifie qu'aucune relation ne peut contenir de doublons, y compris toutes les relations de transition, pas seulement vos "tables".
En suivant ce principe, vous pouvez dire que SELECT length FROM product
ne contient déjà que deux lignes, donc COUNT
correspondant renvoie 2
, ne pas 3
.
Par exemple, dans Rel SGBD, en utilisant la relation donnée dans la question et la syntaxe Tutorial D :
SUMMARIZE product {length} BY {}: {c := COUNT()}
donne:
Soit votre professeur a fait une erreur, soit vous avez mal compris ce qu'elle a dit. Dans le contexte des SGBD relationnels, tels qu'implémentés par divers fournisseurs, la fonction d'agrégation COUNT(<expression>)
renvoie le nombre de valeurs non NULL de <expression>
Dans le jeu de résultats (ou un groupe).
Il existe un cas particulier de COUNT(*)
, qui renvoie le nombre de lignes dans le jeu de résultats ou le groupe, et non le nombre de valeurs de quoi que ce soit. Cela équivaut à COUNT(<constant expression>)
, comme COUNT(1)
.
De nombreuses bases de données prennent en charge COUNT(DISTINCT <expression>)
, qui will renvoie le nombre de valeurs uniques de <expression>
.
Si votre professeur parle de SQL, la déclaration est fausse. COUNT(x)
renverra le nombre de lignes où x IS NOT NULL
y compris les doublons. COUNT(*) or COUNT([constant])
est un cas spécial qui comptera les lignes, même celles où chaque colonne est NULL
. Cependant, les doublons sont toujours comptés, sauf si vous spécifiez COUNT(distinct x)
. Exemple:
with t(x,y) as ( values (null,null),(null,1),(1,null),(1,1) )
select count(*) from t
4
select count(1) from t
4
select count(distinct 1) from t
1
select count(x) from t
2
select count(distinct x) from t
1
COUNT(distinct *)
n'est pas valide AFAIK.
En remarque, NULL introduit un comportement peu intuitif. Par exemple:
SELECT SUM(x) + SUM(y), SUM(x + y) FROM T
4, 2
c'est à dire:
SUM(x)+SUM(y) <> SUM(x+y)
S'il parle d'un système relationnel tel que décrit par exemple par le livre Bases de données, types et modèle relationnel: le troisième manifeste par CJ Date et Hugh Darwen - ce serait une bonne déclaration.
Disons que nous avons la relation:
STUDENTS = Relation(["StudentId", "Name"]
, [{"StudentId":'S1', "Name":'Anne'},
{"StudentId":'S2', "Name":'Anne'},
{"StudentId":'S3', "Name":'Cindy'},
])
SELECT COUNT(NAME) FROM STUDENTS
correspond à:
COUNT(STUDENTS.project(['Name']))
c'est à dire.
COUNT( Relation(["Name"]
, [{"Name":'Anne'},
{"Name":'Cindy'},
]) )
qui retournerait 2 .
Voici comment cela fonctionne dans MS SQL Server
COUNT (*) renvoie le nombre d'éléments dans un groupe. Cela inclut les valeurs NULL et les doublons.
COUNT (ALL expression) évalue l'expression pour chaque ligne d'un groupe et renvoie le nombre de valeurs non nulles.
COUNT (expression DISTINCT) évalue l'expression pour chaque ligne d'un groupe et renvoie le nombre de valeurs non nulles uniques.
Si la table avait ressemblé à ça,
| product |
|id | length | code |
|-------------------|
| 1 | 11 | X00 |
| 2 | 11 | C02 |
| 3 | null | A31 |
vous pouvez vous attendre à ce que la requête renvoie 2, au moins dans Oracle DB, car les valeurs nulles ne sont pas comptées. Les doublons sont cependant comptés très bien.