为什么需要将自己创建的列(例如select 1 as "number"
)放在 MySQL 之后HAVING
而不是WHERE
MySQL 中?
并且有什么缺点而不是做WHERE 1
(写整个定义而不是列名)?
为什么需要将自己创建的列(例如select 1 as "number"
)放在 MySQL 之后HAVING
而不是WHERE
MySQL 中?
并且有什么缺点而不是做WHERE 1
(写整个定义而不是列名)?
为什么您需要将自己创建的列(例如“选择 1 作为数字”)放在 HAVING 之后而不是 MySQL 中的 WHERE 之后?
WHERE
在之前应用GROUP BY
,HAVING
在之后应用(并且可以过滤聚合)。
通常,您不能在这两个子句中引用别名,但允许MySQL
在和中引用SELECT
级别别名。GROUP BY
ORDER BY
HAVING
并且有什么缺点而不是做“WHERE 1”(写整个定义而不是列名)
如果您的计算表达式不包含任何聚合,则将其放入WHERE
子句很可能会更有效。
关于这个问题的所有其他答案都没有触及关键点。
假设我们有一张桌子:
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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
您可以看到WHERE
或HAVING
使用索引,但行不同。
主要区别在于WHERE
不能用于分组项目(例如SUM(number)
),而HAVING
可以。
原因是分组前WHERE
完成,分组完成后完成。HAVING
HAVING
用于过滤GROUP BY
.
例如,要检查重复名称:
SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
这两个将与第一个感觉相同,因为两者都用于表示过滤数据的条件。尽管在任何情况下我们都可以使用“have”代替“where”,但在某些情况下我们不能使用“where”代替“have”。这是因为在选择查询中,“where”在“select”之前过滤数据,而“have”在“select”之后过滤数据。因此,当我们使用实际上不在数据库中的别名时,'where' 无法识别它们,但 'have' 可以。
例如:让表学生包含学生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.*/
WHERE在数据分组前过滤,HAVING在数据分组后过滤。这是一个重要的区别; 被WHERE子句消除的行将不包含在组中。这可能会更改计算值,进而(= 作为结果)可能会影响基于HAVING 子句中使用这些值的那些组被过滤。
并继续,
HAVING与WHERE非常相似,以至于如果没有指定GROUP BY,大多数 DBMS 将它们视为同一事物。不过,您应该自己做出区分。仅将HAVING与GROUP BY 子句结合使用。使用WHERE进行标准行级过滤。
仅与聚合一起使用,但与非聚合语句一起使用如果你有 where 单词将它放在聚合之前(分组依据)