在哪里与HAVING

时间:2010-05-25 13:57:42

标签: mysql sql where-clause having-clause

为什么需要在select 1 as "number"之后放置自己创建的列(例如HAVING)而不是WHERE

是否有任何缺点而不是WHERE 1(编写整个定义而不是列名)?

7 个答案:

答案 0 :(得分:304)

  

为什么你需要在HAVING之后放置你自己创建的列(例如“select 1 as number”)而不是在MySQL中使用WHERE?

WHERE之前应用

GROUP BY,之后应用HAVING(并且可以对聚合进行过滤)。

通常,您可以在这两个子句中引用别名,但MySQL允许在SELECTGROUP BYORDER BY中引用HAVING级别别名。

  

是否有任何缺点而不是做“WHERE 1”(编写整个定义而不是列名)

如果您计算的表达式不包含任何聚合,那么将它放入WHERE子句中可能会更有效。

答案 1 :(得分:258)

所有答案都没有达到关键点。

假设我们有一张表:

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子句在select之前过滤数据,但是HAVING子句在select之后过滤结果数据。

因此,如果表中有许多行,则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使用索引,但行数不同。

答案 2 :(得分:60)

主要区别在于WHERE不能用于分组项目(例如SUM(number))而HAVING可以使用WHERE

原因是<{1}}在分组之前已完成在分组完成后完成<{1>}。

答案 3 :(得分:39)

HAVING用于过滤GROUP BY中的聚合。

例如,要检查重复的名称:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1

答案 4 :(得分:6)

这两个将与第一个相同,因为两者都用于说明过滤数据的条件。虽然我们可以在任何情况下使用'have'来代替'where',但有些情况下我们不能使用'where'而不是'having'。这是因为在选择查询中,“where”在'select'之前过滤数据,而在'select'之后'过滤'数据。因此,当我们使用实际上不在数据库中的别名时,“where”无法识别它们,但“有”可以。

Ex:让学生表包含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.*/

答案 5 :(得分:2)

  数据分组前

WHERE 过滤器,数据分组后 HAVING 过滤器。这是一个重要的区别;那些行   由 WHERE 子句删除的组不会包含在组中。这个   可以改变计算值,这反过来可能影响哪些   根据 HAVING 中这些值的使用过滤组   子句。

摘录自:  本塔堡。 “Sams在10分钟内自学SQL(第4版)  Edition)(Sams教你自己......)。“。

答案 6 :(得分:1)

具有仅与聚合一起使用但具有非聚合语句的情况 如果您在聚合之前将其放在哪里(分组依据)