Utilisation de HAVING sans GROUP BY dans les requêtes SQL

26

Pour utiliser HAVINGdans les requêtes SQL, doit-il y avoir un GROUP BYpour regrouper les noms de colonne?

Existe-t-il des cas particuliers où il est possible d'utiliser HAVINGsans GROUP BYdans les requêtes SQL?

Doivent-ils coexister en même temps?

Ballot d'ordinateur
la source

Réponses:

25

Non.

Ils n'ont pas à coexister, comme le prouve le fait que la requête suivante dans Oracle fonctionne:

select * from dual having 1 = 1;

De même, dans PostgreSQL, la requête suivante fonctionne:

select 1 having 1 = 1;

having Ne nécessite donc pasgroup by .

Avoir est appliqué après la phase d'agrégation et doit être utilisé si vous souhaitez filtrer les résultats d'agrégation. Donc, l'inverse n'est pas vrai, et ce qui suit ne fonctionnera pas:

select a, count(*) as c
from mytable
group by a
where c > 1;

Vous devez remplacer wherepar havingdans ce cas, comme suit:

select a, count(*) as c
from mytable
group by a
having c > 1;

NB Le formulaire de requête suivant fonctionnera également:

select *
from (
  select a, count(*) as c
  from mytable
  group by a
)
where c > 1;

Vous pouvez voir que l'utilisation havingest simplement une version abrégée de cette dernière requête.


En résumé, havingest appliqué après la group byphase alors qu'il whereest appliqué avant la group byphase.

Colin 't Hart
la source
2
Un autre exemple:SELECT MIN(a) AS mina, MAX(a) As maxa FROM mytable HAVING MIN(a) < MAX(a);
ypercubeᵀᴹ
1
Oui. Et PostgreSQL permet la construction suivante select 1 having count(*) = 1;que je n'ai pas encore saisie.
Colin 't Hart
SQL Server le permet aussi, SELECT 1 AS id, 'Colin' AS name;tandis que d'autres comme Oracle ont une dualtable spéciale . Je ne pense pas que l'une de ces syntaxes soit ANSI / ISO SQL (ce qui nécessite FROM).
ypercubeᵀᴹ
Je ne voulais pas dire le manque de frommais la référence à count(*)dans la havingclause sans aucune indication quant aux colonnes sur lesquelles cela est agrégé. Vraisemblablement, il agrège toutes les colonnes de la selectclause.
Colin 't Hart
Ah ok. Oui, je suis d'accord que c'est ce qu'il fait (agréger sur toutes les lignes que vous voulez dire - sur toutes les lignes d'une table vide).
ypercubeᵀᴹ
4

Avoir est utilisé pour filtrer les groupes.

La clause where est utilisée pour filtrer les lignes.

sqlengineer
la source
1
Votre première déclaration n'est pas correcte. havingest appliqué après la phase d'agrégation et peut donc être utilisé pour filtrer les groupes.
Colin 't Hart
1

AVOIR filtre les groupes. Si vous n'avez pas de cause GROUP BY, toutes les lignes présentent un groupe. Donc, si le prédicat dans HAVING est évalué comme vrai, vous obtenez une ligne, sinon aucune ligne.

msi77
la source
1

En l'absence de clause GROUP BY, la requête considère la relation entière comme un seul groupe.

par exemple

     select count(*)
     from dual
     having count(*) > 5;
Vikrant Singh
la source