Je suis tombé sur ce puzzle dans les commentaires ici
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server et PostgreSQL renvoient 1 ligne.
MySQL et Oracle ne renvoient aucune ligne.
Qui est correct? Ou les deux sont-ils également valables?
aggregate
sql-standard
Martin Smith
la source
la source
SELECT COUNT(*) FROM r;
renvoie 1 ligne (avec0
), tandis qu'ilSELECT COUNT(*) FROM r GROUP BY ();
ne renvoie aucune ligne.SELECT 1 WHERE 1=0 HAVING 1=1;
. SQL Server et PostgreSQL renvoient toujours une ligne. Oracle veut FROM DUAL et ne renvoie aucune ligne. MySQL ne compile ni avec FROM DUAL ni sans .SELECT 1 AS t FROM (SELECT 1) tmp WHERE 1=0 HAVING 1=1;
1 ligne sans double et renvoie 0 lignes.<group by clause>
, alors il“GROUP BY ()”
est implicite.". Les deux requêtes ne devraient-elles pas alors renvoyer les mêmes résultats?HAVING
différemment): SQl-fiddle 2: HAVING rend les choses différentesRéponses:
Selon la norme:
veux dire
Citation ISO / IEC 9075-2: 2011 7.10 Règle de syntaxe 1 (partie de la définition de la clause HAVING):
Ok donc c'est assez clair.
Assertion:
1=1
est une véritable condition de recherche. Je ne fournirai aucune citation à ce sujet.Maintenant
équivaut à
Citation ISO / IEC 9075-2: 2011 7.10 Règle générale 1:
Logique: Puisque la condition de recherche est toujours vraie, le résultat est
R
, qui est le résultat du groupe par expression.Ce qui suit est un extrait des Règles générales de 7.9 (la définition du GROUPE PAR CLAUSE)
Nous pouvons donc conclure que
donne une table groupée, composée d'un groupe, avec zéro ligne (puisque R est vide).
Un extrait des règles générales de 7.12, qui définit une spécification de requête (alias une instruction SELECT):
Par conséquent, puisque la table a un groupe, elle doit avoir une ligne de résultat.
Donc
doit renvoyer un jeu de résultats d'une ligne.
QED
la source
Lorsqu'il y a une
HAVING
clause, sansWHERE
clause:...
GROUP BY ()
est alors implicite. Ainsi, la requête doit être équivalente à:... qui devrait regrouper toutes les lignes du tableau en un seul groupe (même si le tableau n'a pas de lignes du tout - c'est toujours un groupe de 0 lignes) et retourner 1 ligne. La
HAVING
laTrue
condition devrait avoir aucun effet après.Sous un angle différent, combien de lignes une requête comme celle-ci doit-elle renvoyer?
Un, zéro ou "zéro ou un, selon que la table est vide ou non"?
Je pense qu'une ligne, peu importe le nombre de lignes
r
.la source
D'après ce que je vois, il semble que SQLServer et PostgerSQL ne se soucient pas du tout de la table:
renvoie également une seule ligne. Même si les documents SQLServer disent
ce n'est pas vrai dans ce cas -
WHERE 1=1
au lieu deHAVING
renvoie le nombre approprié de lignes. Je dirais que c'est un bogue de l'optimiseur (ou au moins un bogue de documentation) ... Le plan SQLServer affiche "Analyse constante" en cas deHAVING
et "analyse de table" pourWHERE
...Le comportement d'Oracle et de Mysql me semble plus logique et correct ...
la source
explain
"Résultat (lignes = 1) ..." pour avoir et "Seq Scan" pour "OERE", il ne regarde pas non plus dans le tableau. .. Je suppose que c'est en quelque sorte lié au fait que "FROM" n'est pas obligatoire dans TSQL et PostgreSQL. Je sais que Mysql ne l'exige pas non plus, mais comme ils prennent en chargedual
, ils analysent probablement la requête un peu différemment. Je suis d'accord, cela ressemble à une spéculation, mais j'espère que cela a du sens.