在哪里与拥有

Posted

技术标签:

【中文标题】在哪里与拥有【英文标题】:WHERE vs HAVING 【发布时间】:2011-02-23 17:16:37 【问题描述】:

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

除了WHERE 1(写整个定义而不是列名)还有什么缺点吗?

【问题讨论】:

【参考方案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 和 value 从 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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

您可以看到WHEREHAVING 使用索引,但行不同。

【讨论】:

感谢您提到 EXPLAIN! 因为 HAVING 子句在 select 之后过滤数据,所以 WHERE 子句会更有效。所以如果这是真的,我们什么时候必须使用 HAVING 而不是 WHERE? @grep 如果要在 select 后过滤数据,则需要 HAVING 子句,通常我们将其与 GROUP BY 子句一起使用,例如: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 子句被添加到 SQL 中,因为 WHERE 关键字不能与聚合函数一起使用。【参考方案2】:

WHERE 在数据分组前过滤,HAVING 在数据分组后过滤。这是一个重要的区别;是的行 被 WHERE 子句消除的将不包含在组中。这 可以改变计算值,反过来(=作为结果)可能会影响 根据 HAVING 中这些值的使用情况过滤组 子句。

然后继续,

HAVINGWHERE 非常相似,以至于大多数 DBMS 将它们视为相同 如果没有指定 GROUP BY 的话。不过,你应该这样做 区分自己。 HAVING 仅与 GROUP BY 一起使用 条款。使用 WHERE 进行标准行级过滤。

摘自: Forta, Ben. “Sams Teach Yourself SQL in 10 Minutes (5th Edition) (Sams Teach Yourself...).”.

【讨论】:

【参考方案3】:

Having 仅与聚合一起使用,而 where 与非聚合语句一起使用 如果你有 where 词放在聚合之前(分组)

【讨论】:

【参考方案4】:

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

例如:让表 Student 包含 student_id,name,birthday,address。假设生日是 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.*/

【讨论】:

这个真实的例子充分阐明了WHEREHAVING之间的区别。 清楚地显示了Have 和where 之间的区别。谢谢。【参考方案5】:

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

例如,检查重复名称:

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

【讨论】:

对现存的一些人来说是真的。您仍然可以将整个“在哪里”放在有子句中。 另见***.com/questions/2905292/…【参考方案6】:

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

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

【讨论】:

【参考方案7】:

为什么您需要将自己创建的列(例如“选择 1 作为数字”)放在 HAVING 之后而不是 MySQL 中的 WHERE 之后?

WHEREGROUP BY 之前应用,HAVING 在之后应用(并且可以过滤聚合)。

一般来说,您不能在这两个子句中引用别名,但MySQL 允许在GROUP BYORDER BYHAVING 中引用SELECT 级别名。

除了执行“WHERE 1”(写整个定义而不是列名)之外,还有什么缺点吗

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

【讨论】:

以上是关于在哪里与拥有的主要内容,如果未能解决你的问题,请参考以下文章

哪个 SQL 语句更快? (拥有与在哪里......)

在尝试创建迁移时,您如何找到或知道“非拥有”实体类型在哪里?

BigQuery RANK() 在拥有或在哪里子句

Ubuntu 上的 dotnet 运行时安装在哪里?

小程序和app的优势各在哪里?

689期 | 巨无霸的软肋在哪里? - 如何在一个已经拥有巨大存量的强大敌人身边生存下来。