为什么WHERE和HAVING作为SQL中的单独子句存在?

时间:2014-03-27 17:31:18

标签: sql where-clause having-clause

我理解SQL查询中WHEREHAVING之间的区别,但我不明白为什么它们是单独的子句。难道它们不能组合成一个可以处理聚合和非聚合数据的单个子句吗?

4 个答案:

答案 0 :(得分:2)

可以吗?当然,但是在后端它会像现在一样,因为你必须先聚合一些东西才能根据聚合进行过滤。最终这就是原因,它是不同过程的逻辑分离。为什么要浪费资源汇总您可以使用WHERE过滤的记录?

答案 1 :(得分:2)

这是规则。 如果条件引用聚合函数,请将该条件放在HAVING子句中。否则,请使用WHERE子句。

这是另一条规则:除非您也使用GROUP BY,否则您无法使用HAVING。

主要区别是WHERE不能用于分组项目(例如SUM(数字))而HAVING可以。原因是在分组之前完成WHERE并且在分组之后完成HAVING分组完成。

另一个差异 IS WHERE子句要求条件成为表中的列,但HAVING子句可以同时使用列和别名。

这就是区别:

SELECT `value` v FROM `table` WHERE `v`>5;

错误#1054 - 未知栏' v'在' where子句'

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 :(得分:1)

这个问题只能由设计师完全回答,因为它要求意图。但其含义是,两个条款仅针对聚合数据与非聚合数据执行相同的操作。那不是真的。 " HAVING子句通常与GROUP BY子句一起使用,以过滤聚合值的结果。 但是,可以在没有GROUP BY的情况下指定HAVING。 "

据我所知,重要的是" HAVING子句指定在WHERE子句过滤后应用的其他过滤器。"

http://technet.microsoft.com/en-us/library/ms179270(v=sql.105).aspx

答案 3 :(得分:1)

这个问题似乎说明了一种误解,即WHEREHAVING都缺少完整处理查询所需信息的1/2。

考虑以下SQL:

drop table if exists foo; create table foo (
  ID int,
  bar int
); insert into foo values (1, 1);

select now() as d, bar as b
from foo
where bar = 1 and d <= now()
having bar = 1 and ID = 1
;

where子句中,d不可用,因为尚未处理select ed项尚未创建它。

having条款ID已被丢弃,因为它不是select。在聚合查询中,ID在多行组合成一行的上下文中甚至可能没有意义。 ID join在{{1}}将不同的表放入单个结果时也可能毫无意义。