我在WHERE
和HAVING
上看到了各种讨论。我还有一个问题:HAVING
仅在考虑聚合时使用,或者可以用于更一般的术语:每当您在查询中创建或别名字段时?
我知道在可能的情况下应始终使用WHERE
。
答案 0 :(得分:9)
HAVING
指定搜索SELECT
语句中使用的内容。
换句话说。
HAVING
适用于群组。
WHERE
适用于行。
答案 1 :(得分:6)
HAVING
仅适用于涉及与GROUP BY
子句一起使用的聚合的条件。例如。 COUNT
,SUM
,AVG
,MAX
,MIN
。 WHERE
适用于任何非聚合条件。它们甚至可以在同一查询中一起使用。例如
SELECT t1.id, COUNT(*) FROM table1 AS t1
INNER JOIN table2 AS t2 ON t2.t1_id = t1.id
WHERE t1.score > 50
GROUP BY t1.id HAVING COUNT(*) > 2;
原来我不知道有HAVING
的非聚合使用情况。下面使用别名的查询仅适用于HAVING
关键字,而不是WHERE
关键字。请参阅我在MySQL中的测试:
mysql> create table my_contacts (
-> id int unsigned primary key auto_increment,
-> first_name varchar(32) not null,
-> last_name varchar(32) not null,
-> index (last_name, first_name)
-> ) engine=innodb;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into my_contacts (first_name, last_name)
-> values ('Randy', 'Jackson'), ('Billy', 'Johnson'), ('Sam', 'Harris'), ('Lenny', 'Benson'), ('Sue', 'Flax');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> SELECT last_name AS l FROM my_contacts HAVING l LIKE '%son';
+---------+
| l |
+---------+
| Benson |
| Jackson |
| Johnson |
+---------+
3 rows in set (0.00 sec)
mysql> SELECT last_name AS l FROM my_contacts WHERE l LIKE '%son';
ERROR 1054 (42S22): Unknown column 'l' in 'where clause'
我现在已经在SQL Server上测试了HAVING
的新用法,它确实不工作。所以这可能是仅限MySQL的功能。此外,@ Denis在评论中指出,只有当列/别名可以消除歧义并且它仅适用于某些引擎时,此技巧才有效。
答案 2 :(得分:6)
WHERE
子句用于限制记录,也用于
查询优化器以确定要使用的索引和表。 HAVING
是最终结果集上的“过滤器”,并在之后应用
GROUP BY
,因此sql无法使用它来优化查询。
WHERE
。 HAVING
提取所有行,然后过滤结果。
因此WHERE
不能用于聚合函数,因为它们需要提取完整的行集。
答案 3 :(得分:4)
HAVING
子句,并且您尝试根据其中一个分组字段进行过滤,则会使用 GROUP BY
; WHERE
用于过滤否则。
例如
select StudentName from students where Age > 20
select className, count(studentId) from classes group by className
having count(studentId) > 10