WHERE vs HAVING

后端 未结 7 2179
北荒
北荒 2020-11-22 08:20

Why do you need to place columns you create yourself (for example select 1 as \"number\") after HAVING and not WHERE in MySQL?

7条回答
  •  一个人的身影
    2020-11-22 08:29

    All other answers on this question didn't hit upon the key point.

    Assume we have a table:

    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
    

    And have 10 rows with both id and value from 1 to 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);
    

    Try the following 2 queries:

    SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
    SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows
    

    You will get exactly the same results, you can see the HAVING clause can work without GROUP BY clause.


    Here's the difference:

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

    Error #1054 - Unknown column 'v' in 'where clause'

    SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows
    

    WHERE clause allows a condition to use any table column, but it cannot use aliases or aggregate functions. HAVING clause allows a condition to use a selected (!) column, alias or an aggregate function.

    This is because WHERE clause filters data before select, but HAVING clause filters resulting data after select.

    So put the conditions in WHERE clause will be more efficient if you have many many rows in a table.

    Try EXPLAIN to see the key difference:

    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 |
    +----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
    

    You can see either WHERE or HAVING uses index, but the rows are different.

提交回复
热议问题