为什么你需要把你自己创建的列(例如,选择1作为“数字”)后有,而不是哪里在MySQL?

如果不使用WHERE 1(编写整个定义而不是列名),有什么缺点吗?


当前回答

对这个问题的其他回答都没有抓住要害。

假设我们有一个表:

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 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都使用索引,但行是不同的。

其他回答

对这个问题的其他回答都没有抓住要害。

假设我们有一个表:

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 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都使用索引,但行是不同的。

HAVING用于筛选GROUP BY中的聚合。

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

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

主要区别是WHERE不能用于分组项(例如SUM(number)),而HAVING可以。

原因是WHERE是在分组之前执行的,HAVING是在分组之后执行的。

Having仅用于聚合语句,但用于非聚合语句 如果你有where word,把它放在聚合(分组by)之前

这两个感觉和第一个一样,因为它们都用来表示过滤数据的条件。尽管在任何情况下我们都可以用“having”来代替“where”,但在某些情况下我们不能用“where”来代替“having”。这是因为在选择查询中,' where '在' select '之前过滤数据,而' having '在' select '之后过滤数据。因此,当我们使用实际上不在数据库中的别名时,' where '不能识别它们,但' having '可以。

例如:让Student表包含student_id,姓名,生日,地址。假设生日的类型是date。

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.*/