Answers:
关于这个问题的所有其他答案都没有找到重点。
假设我们有一张桌子:
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
并有10行ID和值都在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);
请尝试以下2个查询:
SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows
您将获得完全相同的结果,可以看到HAVING子句可以在没有GROUP BY子句的情况下工作。
区别在于:
SELECT `value` v FROM `table` WHERE `v`>5;
错误#1054-“ where子句”中的未知列“ v”
SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows
WHERE子句允许条件使用任何表列,但不能使用别名或聚合函数。HAVING子句允许条件使用选择的(!)列,别名或聚合函数。
这是因为WHERE子句在选择之前过滤数据,而HAVING子句在选择之后过滤结果数据。
因此,如果表中有许多行,则将条件放在WHERE子句中将更加有效。
尝试EXPLAIN查看主要区别:
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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
您可以看到WHERE或HAVING使用索引,但是行不同。
SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
...HAVING clause can use both column and alias.
到...HAVING clause can use either column or alias.
和改变...WHERE clause will be more effective
,以...WHERE clause will be more efficient
HAVING
用于过滤您中的汇总GROUP BY
。
例如,要检查重复的名称:
SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
这两个与第一个相同,因为它们都用来表示过滤数据的条件。尽管在任何情况下都可以用“有”代替“有”,但是在某些情况下,我们不能用“有”代替“有”。这是因为在选择查询中,“位置”在“选择”之前过滤数据,而“在”“选择”之后过滤数据。因此,当我们使用不在数据库中的别名时,“ where”无法识别它们,而“ having”则可以。
例如:让学生表包含student_id,姓名,生日,地址。假设生日是日期类型。
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.*/
WHERE
和之间的区别HAVING
。
WHERE在数据分组之前过滤,而HAVING在数据分组之后过滤。这是一个重要的区别; 由WHERE子句消除的行将不包含在组中。这可能会更改计算出的值,从而又会影响基于HAVING 子句中这些值的使用而过滤出哪些组的结果。
并继续
拥有与WHERE非常相似,因此,如果未指定GROUP BY,则大多数DBMS会将它们视为同一事物。但是,您应该自己进行区分。仅将HAVING与GROUP BY 子句结合使用。使用WHERE进行标准的行级过滤。