DONDE vs TENER

247

¿Por qué necesita colocar columnas que cree usted mismo (por ejemplo select 1 as "number") después HAVINGy no WHEREen MySQL?

¿Y hay inconvenientes en lugar de hacerlo WHERE 1(escribir la definición completa en lugar del nombre de una columna)?

baloo
fuente

Respuestas:

323

¿Por qué es necesario colocar columnas que usted mismo cree (por ejemplo, "seleccione 1 como número") después de TENER y NO DÓNDE en MySQL?

WHEREse aplica antes GROUP BY, HAVINGse aplica después (y puede filtrar en agregados).

En general, puede hacer referencia a alias en ninguna de estas cláusulas, pero MySQLpermite hacer referencia a SELECTalias de nivel en GROUP BY, ORDER BYy HAVING.

¿Y hay inconvenientes en lugar de hacer "WHERE 1" (escribir la definición completa en lugar del nombre de una columna)

Si su expresión calculada no contiene ningún agregado, ponerlo en la WHEREcláusula probablemente será más eficiente.

Quassnoi
fuente
289

Todas las demás respuestas a esta pregunta no dieron en el punto clave.

Supongamos que tenemos una mesa:

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

Y tenga 10 filas con id y valor de 1 a 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);

Pruebe las siguientes 2 consultas:

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

Obtendrá exactamente los mismos resultados, puede ver que la cláusula HAVING puede funcionar sin la cláusula GROUP BY.


Aquí está la diferencia:

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

Error # 1054 - Columna desconocida 'v' en 'cláusula where'

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

La cláusula WHERE permite que una condición use cualquier columna de tabla, pero no puede usar alias o funciones agregadas. La cláusula HAVING permite que una condición use una columna (!) Seleccionada, un alias o una función agregada.

Esto se debe a que la cláusula WHERE filtra los datos antes de la selección, pero la cláusula HAVING filtra los datos resultantes después de la selección.

Por lo tanto, ponga las condiciones en la cláusula WHERE será más eficiente si tiene muchas filas en una tabla.

Intente EXPLICAR para ver la diferencia clave:

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

Puede ver WHERE o HAVING usa index, pero las filas son diferentes.

Ahogado
fuente
32
¡Agradezco que hayas mencionado EXPLICAR!
paiego
Debido a que la cláusula HAVING filtra los datos después de la selección, la cláusula WHERE será más efectiva. Entonces, si esto es cierto, ¿cuándo debemos usar HAVING en lugar de WHERE?
grep
55
@grep En caso de que tenga que filtrar datos después de la selección, necesita la cláusula HAVING, generalmente la usamos con la cláusula GROUP BY, por ejemplo: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned el
1
Excelente post. Un par de aclaraciones sugeridas: Cambiar ...HAVING clause can use both column and alias.a ...HAVING clause can use either column or alias.y el cambio ...WHERE clause will be more effectivea...WHERE clause will be more efficient
rmirabelle
2
La cláusula HAVING se agregó a SQL porque la palabra clave WHERE no se pudo usar con funciones agregadas.
Shashank Vivek
62

La principal diferencia es que WHEREno se puede usar en elementos agrupados (como SUM(number)), mientras que HAVINGsí.

La razón es que WHEREse realiza antes de la agrupación y HAVINGse realiza después de que se realiza la agrupación.

David Brunelle
fuente
39

HAVINGse utiliza para filtrar agregaciones en su GROUP BY.

Por ejemplo, para verificar nombres duplicados:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin
fuente
1
Es cierto para algunos existentes. Todavía puede poner todo su 'Dónde' en la cláusula have.
David Brunelle
8

Estos 2 se sentirán igual que los primeros, ya que ambos se usan para decir acerca de una condición para filtrar datos. Aunque podemos usar 'tener' en lugar de 'dónde' en cualquier caso, hay casos en los que no podemos usar 'dónde' en lugar de 'tener'. Esto se debe a que en una consulta de selección, 'donde' filtra datos antes de 'seleccionar' mientras 'tiene' filtrar datos después de 'seleccionar'. Entonces, cuando usamos nombres de alias que no están realmente en la base de datos, 'where' no puede identificarlos pero 'having' sí.

Ej: deje que la tabla Alumno contenga student_id, nombre, cumpleaños, dirección. Asumir que el cumpleaños es de tipo fecha.

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
fuente
1
Este ejemplo de la vida real aclara completamente la diferencia entre WHEREy HAVING.
WM
Muestra claramente la diferencia entre Tener y dónde. Gracias.
MarcoZen
3

WHERE filtra antes de que se agrupen los datos y HAVING filtra después de que se agrupan los datos. Esta es una distinción importante; las filas que se eliminan mediante una cláusula WHERE no se incluirán en el grupo. Esto podría cambiar los valores calculados que, a su vez (= como resultado) podrían afectar qué grupos se filtran en función del uso de esos valores en la cláusula HAVING .

Y continúa

TENER es tan similar a DONDE que la mayoría de los DBMS los tratan como lo mismo si no se especifica GROUP BY . Sin embargo, debe hacer esa distinción usted mismo. Use HAVING solo junto con las cláusulas GROUP BY . Use WHERE para el filtrado de nivel de fila estándar.

Extracto de: Forta, Ben. "Sams Teach Yourself SQL en 10 minutos (5ª edición) (Sams Teach Yourself ...)".

snr
fuente
1

Tener solo se usa con agregación, pero donde con declaraciones de no agregación Si tiene donde la palabra lo pone antes de la agregación (agrupar por)

Hos Mercury
fuente