DOVE vs AVERE


247

Perché è necessario posizionare le colonne create dall'utente (ad esempio select 1 as "number") dopo HAVINGe non WHEREin MySQL?

E ci sono degli svantaggi invece di fare WHERE 1(scrivere l'intera definizione invece del nome di una colonna)?

Risposte:


323

Perché è necessario posizionare colonne create dall'utente (ad esempio "seleziona 1 come numero") dopo AVERE e non DOVE in MySQL?

WHEREviene applicato prima GROUP BY, HAVINGviene applicato dopo (e può filtrare sugli aggregati).

In generale, è possibile fare riferimento alias in alcuno di queste clausole, ma MySQLconsente riferimento SELECTalias livello in GROUP BY, ORDER BYe HAVING.

E ci sono degli svantaggi invece di fare "WHERE 1" (scrivendo l'intera definizione invece del nome di una colonna)

Se la tua espressione calcolata non contiene alcun aggregato, inserirla nella WHEREclausola molto probabilmente sarà più efficiente.


289

Tutte le altre risposte a questa domanda non hanno colpito il punto chiave.

Supponiamo di avere un tavolo:

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

E hanno 10 righe con id e valore compresi tra 1 e 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);

Prova le seguenti 2 query:

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

Otterrai esattamente gli stessi risultati, puoi vedere che la clausola HAVING può funzionare senza la clausola GROUP BY.


Ecco la differenza:

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

Errore n. 1054 - Colonna sconosciuta "v" in "clausola where"

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

La clausola WHERE consente a una condizione di utilizzare qualsiasi colonna della tabella, ma non può utilizzare alias o funzioni aggregate. La clausola HAVING consente a una condizione di utilizzare una colonna, un alias o una funzione aggregata selezionata.

Questo perché la clausola WHERE filtra i dati prima della selezione, ma la clausola HAVING filtra i dati risultanti dopo la selezione.

Quindi inserisci le condizioni nella clausola WHERE sarà più efficiente se hai molte molte righe in una tabella.

Prova EXPLAIN per vedere la differenza chiave:

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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Puoi vedere WHERE o HAVING utilizza l'indice, ma le righe sono diverse.


32
Apprezzo che tu abbia citato EXPLAIN!
paiego

A causa della clausola HAVING filtra i dati dopo la selezione, la clausola WHERE sarà più efficace. Quindi, se questo è vero, quando dobbiamo usare HAVING anziché WHERE?
Grep,

5
@grep Nel caso in cui sia necessario filtrare i dati dopo la selezione, è necessaria la clausola HAVING, di solito li utilizziamo con la clausola GROUP BY, ad esempio: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned

1
Post eccellente. Un paio di precisazioni suggerite: Cambiare ...HAVING clause can use both column and alias.per ...HAVING clause can use either column or alias.e cambiare ...WHERE clause will be more effectivea...WHERE clause will be more efficient
rmirabelle

2
La clausola HAVING è stata aggiunta a SQL perché non è stato possibile utilizzare la parola chiave WHERE con le funzioni di aggregazione.
Shashank Vivek,

62

La differenza principale è che WHEREnon può essere utilizzato su articoli raggruppati (come SUM(number)) mentre HAVINGcan.

Il motivo è l' WHEREè fatto prima che il raggruppamento e HAVINGviene fatto dopo il raggruppamento è fatto.



8

Questi 2 saranno i primi come entrambi vengono usati per dire una condizione per filtrare i dati. Sebbene possiamo usare "avere" al posto di "dove" in ogni caso, ci sono casi in cui non possiamo usare "dove" invece di "avere". Questo perché in una query di selezione, "dove" filtra i dati prima di "seleziona" mentre "avendo" filtra i dati dopo "seleziona". Pertanto, quando utilizziamo nomi di alias che non si trovano effettivamente nel database, "dove" non è in grado di identificarli ma "possibilmente" può.

Esempio: lascia che la tabella Studente contenga student_id, nome, data di nascita, indirizzo. Supponi che la data di nascita sia di tipo data.

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.*/

1
Questo esempio di vita reale chiarisce completamente la differenza tra WHEREe HAVING.
WM,

Mostra chiaramente la differenza tra Avere e dove. Grazie.
MarcoZen,

3

DOVE filtra prima che i dati vengano raggruppati e HAVING filtra dopo che i dati sono stati raggruppati. Questa è una distinzione importante; le righe eliminate da una clausola WHERE non verranno incluse nel gruppo. Questo potrebbe cambiare i valori calcolati che, a loro volta (= come risultato) potrebbero influenzare quali gruppi vengono filtrati in base all'uso di tali valori nella clausola HAVING .

E continua

HAVING è così simile a DOVE che la maggior parte dei DBMS li tratta come la stessa cosa se non viene specificato GROUP BY . Tuttavia, dovresti fare tu stesso questa distinzione. Utilizzare HAVING solo in combinazione con le clausole GROUP BY . Utilizzare WHERE per il filtro standard a livello di riga.

Estratto da: Forta, Ben. "Sams Teach Yourself SQL in 10 Minutes (5th Edition) (Sams Teach Yourself ...).".


1

Avere viene utilizzato solo con aggregazione ma dove con istruzioni non di aggregazione Se si dispone di dove la parola lo inserisce prima dell'aggregazione (raggruppa per)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.