O vs vs AVOIR

247

Pourquoi avez-vous besoin de placer des colonnes que vous créez vous-même (par exemple select 1 as "number") après HAVINGet non WHEREdans MySQL?

Et y a-t-il des inconvénients au lieu de le faire WHERE 1(écrire toute la définition au lieu d'un nom de colonne)?

baloo
la source

Réponses:

323

Pourquoi avez-vous besoin de placer des colonnes que vous créez vous-même (par exemple "sélectionnez 1 comme nombre") après AVOIR et non OERE dans MySQL?

WHEREest appliqué avant GROUP BY, HAVINGest appliqué après (et peut filtrer sur les agrégats).

En général, vous ne pouvez référencer des alias dans aucune de ces clauses, mais MySQLpermet de référencer des SELECTalias de niveau dans GROUP BY, ORDER BYet HAVING.

Et y a-t-il des inconvénients au lieu de faire "WHERE 1" (écrire la définition entière au lieu d'un nom de colonne)

Si votre expression calculée ne contient aucun agrégat, la mettre dans la WHEREclause sera probablement plus efficace.

Quassnoi
la source
289

Toutes les autres réponses à cette question n'ont pas atteint le point clé.

Supposons que nous ayons une table:

CREATE TABLE `table` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `value` int(10) unsigned NOT NULL,
 PRIMARY KEY (`id`),
 KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Et avoir 10 lignes avec à la fois id et valeur de 1 à 10:

INSERT INTO `table`(`id`, `value`) VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5),(6, 6),(7, 7),(8, 8),(9, 9),(10, 10);

Essayez les 2 requêtes suivantes:

SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows

Vous obtiendrez exactement les mêmes résultats, vous pouvez voir que la clause HAVING peut fonctionner sans la clause GROUP BY.


Voici la différence:

SELECT `value` v FROM `table` WHERE `v`>5;

Erreur # 1054 - Colonne inconnue 'v' dans la clause 'where'

SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows

La clause WHERE permet à une condition d'utiliser n'importe quelle colonne de table, mais elle ne peut pas utiliser d'alias ou de fonctions d'agrégation. La clause HAVING permet à une condition d'utiliser une colonne (!), Un alias ou une fonction d'agrégation sélectionnée.

En effet, la clause WHERE filtre les données avant la sélection, mais la clause HAVING filtre les données résultantes après la sélection.

Donc, mettre les conditions dans la clause WHERE sera plus efficace si vous avez beaucoup de lignes dans une table.

Essayez EXPLAIN pour voir la différence clé:

EXPLAIN SELECT `value` v FROM `table` WHERE `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table | range | value         | value | 4       | NULL |    5 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+

EXPLAIN SELECT `value` v FROM `table` having `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table | index | NULL          | value | 4       | NULL |   10 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Vous pouvez voir WHERE ou HAVING utilise l'index, mais les lignes sont différentes.

Poisson-noyé
la source
32
J'apprécie que vous ayez mentionné EXPLAIN!
paiego
En raison de la clause HAVING qui filtre les données après la sélection, la clause WHERE sera plus efficace. Donc, si cela est vrai, quand devons-nous utiliser HAVING au lieu de WHERE?
grep
5
@grep Dans le cas où vous devez filtrer les données après la sélection, vous avez besoin de la clause HAVING, généralement nous l'utilisons avec la clause GROUP BY, par exemple: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrown
1
Excellent poste. Quelques clarifications suggérées: Changement ...HAVING clause can use both column and alias.vers ...HAVING clause can use either column or alias.et changement ...WHERE clause will be more effectivevers...WHERE clause will be more efficient
rmirabelle
2
La clause HAVING a été ajoutée à SQL car le mot clé WHERE n'a pas pu être utilisé avec des fonctions d'agrégation.
Shashank Vivek
62

La principale différence est qu'il WHEREne peut pas être utilisé sur un élément groupé (comme SUM(number)) alors queHAVING peut.

La raison en est que le WHEREprocessus est effectué avant le regroupement et HAVINGest effectué après le regroupement.

David Brunelle
la source
39

HAVINGest utilisé pour filtrer les agrégations dans votre fichier GROUP BY.

Par exemple, pour rechercher des noms en double:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin
la source
1
C'est vrai pour certains. Vous pouvez toujours mettre tout votre «Où» dans la clause having.
David Brunelle
8

Ces 2 seront les mêmes que les premiers, car les deux sont utilisés pour dire une condition pour filtrer les données. Bien que nous puissions utiliser "avoir" à la place de "où" dans tous les cas, il y a des cas où nous ne pouvons pas utiliser "où" au lieu de "avoir". En effet, dans une requête de sélection, «où» filtre les données avant «sélectionner» tout en «ayant» les données de filtre après «sélectionner». Ainsi, lorsque nous utilisons des noms d'alias qui ne figurent pas réellement dans la base de données, «où» ne peut pas les identifier mais «ayant» le peut.

Ex: laissez la table Student contenir student_id, nom, anniversaire, adresse. Supposons que l'anniversaire est de type date.

SELECT * FROM Student WHERE YEAR(birthday)>1993; /*this will work as birthday is in database.if we use having in place of where too this will work*/

SELECT student_id,(YEAR(CurDate())-YEAR(birthday)) AS Age FROM Student HAVING Age>20; 
/*this will not work if we use ‘where’ here, ‘where’ don’t know about age as age is defined in select part.*/
Nuwantha
la source
1
Cet exemple concret clarifie pleinement la différence entre WHEREet HAVING.
WM
Montre clairement la différence entre avoir et où. Merci.
MarcoZen
3

WHERE filtre avant que les données soient groupées, et HAVING filtres après que les données sont groupées. Cette distinction est importante; les lignes supprimées par une clause WHERE ne seront pas incluses dans le groupe. Cela pourrait modifier les valeurs calculées qui, à leur tour (= en conséquence) pourraient affecter les groupes qui sont filtrés en fonction de l'utilisation de ces valeurs dans la clause HAVING .

Et continue,

HAVING est tellement similaire à WHERE que la plupart des SGBD les traitent comme la même chose si aucun GROUP BY n'est spécifié. Néanmoins, vous devez faire cette distinction vous-même. Utilisez HAVING uniquement conjointement avec les clauses GROUP BY . Utilisez WHERE pour le filtrage de niveau ligne standard.

Extrait de: Forta, Ben. «Sams vous enseigne le SQL en 10 minutes (5e édition) (Sams vous enseigne ...).».

snr
la source
1

Avoir n'est utilisé qu'avec l'agrégation mais où avec les instructions de non agrégation Si vous avez où le mot le place avant l'agrégation (grouper par)

Hos Mercury
la source