在哪里与拥有


247

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

还有没有其他弊端WHERE 1(编写整个定义而不是列名)?

Answers:


323

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

WHERE被施加之前GROUP BYHAVING被后应用(并且可以在聚集体筛选)。

在一般情况下,你可以在没有这些条款的引用别名,但MySQL允许引用SELECT在级别别名GROUP BYORDER BYHAVING

还有什么缺点,而不是做“ WHERE 1”(写整个定义而不是列名)

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


289

关于这个问题的所有其他答案都没有找到重点。

假设我们有一张桌子:

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


32
我感谢您提到了EXPLAIN!
paiego,2013年

由于HAVING子句会在选择后过滤数据,因此WHERE子句会更有效。因此,如果这是真的,那么我们何时必须使用HAVING而不是WHERE?
grep 2015年

5
@grep如果选择后必须过滤数据,则需要HAVING子句,通常我们将其与GROUP BY子句一起使用,例如: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrown 2015年

1
优秀的职位。一对夫妇提出澄清:更改...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
rmir​​abelle

2
HAVING子句已添加到SQL,因为WHERE关键字不能与聚合函数一起使用。
Shashank Vivek

62

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

原因是在分组之前WHERE完成了,而在分组HAVING完成之后完成了。



8

这两个与第一个相同,因为它们都用来表示过滤数据的条件。尽管在任何情况下都可以用“有”代替“有”,但是在某些情况下,我们不能用“有”代替“有”。这是因为在选择查询中,“位置”在“选择”之前过滤数据,而“在”“选择”之后过滤数据。因此,当我们使用不在数据库中的别名时,“ 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.*/

1
这个真实的例子充分阐明了WHERE和之间的区别HAVING
WM

清楚地显示Haveing和where之间的区别。谢谢。
MarcoZen

3

WHERE在数据分组之前过滤,而HAVING在数据分组之后过滤。这是一个重要的区别; 由WHERE子句消除的行将不包含在组中。这可能会更改计算出的值,从而又会影响基于HAVING 子句中这些值的使用而过滤出哪些组的结果。

并继续

拥有WHERE非常相似,因此,如果未指定GROUP BY,则大多数DBMS会将它们视为同一事物。但是,您应该自己进行区分。仅将HAVINGGROUP BY 子句结合使用。使用WHERE进行标准的行级过滤。

摘录自: 本塔·福塔。“ Sams在10分钟内自学SQL(第5版)(Sams自学……)。”。


1

具有仅与聚合一起使用,但与非聚合语句一起使用,如果在聚合之前将其放在何处(分组依据)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.