DONDE vs TENER

Resuelto baloo asked hace 14 años • 7 respuestas

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

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

baloo avatar May 25 '10 20:05 baloo
Aceptado

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

Supongamos que tenemos una tabla:

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 del 1 al 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 HAVINGcláusula puede funcionar sin la cláusula GROUP BY.


Aquí está la diferencia:

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

La consulta anterior generará un error: Error n.º 1054: columna desconocida 'v' en la 'cláusula Where'

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

WHERELa cláusula permite que una condición use cualquier columna de la tabla, pero no puede usar alias ni funciones agregadas. HAVINGLa cláusula permite que una condición utilice una columna seleccionada (!), un alias o una función agregada.

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

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

Intente EXPLAINver 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 que WHEREo HAVINGusa el índice, pero las filas son diferentes.

Fishdrowned avatar Sep 10 '2013 04:09 Fishdrowned

¿Por qué necesita colocar columnas que usted mismo crea (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, no puede hacer referencia a alias en ninguna de estas cláusulas, pero permite MySQLhacer referencia SELECTa alias de nivel en y .GROUP BYORDER BYHAVING

¿Y hay alguna desventaja en lugar de hacer "DÓNDE 1" (escribir la definición completa en lugar de un nombre de columna)?

Si su expresión calculada no contiene ningún agregado, WHERElo más probable es que sea más eficiente incluirla en la cláusula.

Quassnoi avatar May 25 '2010 13:05 Quassnoi

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

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

David Brunelle avatar May 25 '2010 14:05 David Brunelle

HAVINGse utiliza para filtrar agregaciones en su GROUP BY.

Por ejemplo, para comprobar si hay nombres duplicados:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin avatar May 25 '2010 14:05 Kevin McKelvin