HAVING
is only for conditions involving aggregates used in conjunction with the GROUP BY
clause. eg. COUNT
, SUM
, AVG
, MAX
, MIN
. WHERE
is for any non-aggregage conditions. They can even be used together in the same query. eg.
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;
Update #1:
Turns out there is a non-aggregate usage of HAVING
that I didn't know about. The query below which uses an alias only works with the HAVING
keyword, not the WHERE
keyword. See my test in 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'
Update #2:
I've now tested the novel use of HAVING
on SQL Server and it does not work. So this may be a MySQL-only feature. Also, @Denis pointed out in the comments that this trick only works if the column/alias can be disambiguated and it only works on some engines.