DONDE vs TENER
¿Por qué necesita colocar columnas que usted mismo crea (por ejemplo select 1 as "number"
) después HAVING
y no WHERE
en MySQL?
¿Y hay alguna desventaja en lugar de hacerlo WHERE 1
(escribir la definición completa en lugar del nombre de una columna)?
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 HAVING
clá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
WHERE
La cláusula permite que una condición use cualquier columna de la tabla, pero no puede usar alias ni funciones agregadas.
HAVING
La cláusula permite que una condición utilice una columna seleccionada (!), un alias o una función agregada.
Esto se debe a que WHERE
la cláusula filtra los datos antes de la selección, pero HAVING
la cláusula filtra los datos resultantes después de la selección.
Por lo tanto, poner las condiciones en WHERE
la cláusula será más eficiente si tiene muchas filas en una tabla.
Intente EXPLAIN
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 que WHERE
o HAVING
usa el índice, pero las filas son diferentes.
¿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?
WHERE
se aplica antes GROUP BY
, HAVING
se aplica después (y puede filtrar en agregados).
En general, no puede hacer referencia a alias en ninguna de estas cláusulas, pero permite MySQL
hacer referencia SELECT
a alias de nivel en y .GROUP BY
ORDER BY
HAVING
¿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, WHERE
lo más probable es que sea más eficiente incluirla en la cláusula.
La principal diferencia es que WHERE
no se puede utilizar en elementos agrupados (como SUM(number)
), mientras que sí HAVING
se puede.
La razón es que se WHERE
realiza antes de la agrupación y después de que se realiza la agrupación.HAVING
HAVING
se 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