WHERE vs HAVING

247

Por que você precisa colocar colunas que você mesmo criou (por exemplo select 1 as "number") depois HAVINGe não WHEREno MySQL?

E existem desvantagens em vez de fazer WHERE 1(escrever a definição inteira em vez de um nome de coluna)?

baloo
fonte

Respostas:

323

Por que você precisa colocar as colunas criadas por você mesmo (por exemplo, "selecione 1 como número") após HAVING e não WHERE no MySQL?

WHEREé aplicado antes GROUP BY, HAVINGé aplicado depois (e pode filtrar em agregados).

Em geral, você pode referenciar aliases em nenhuma dessas cláusulas, mas MySQLpermite referenciar SELECTaliases de nível em GROUP BY, ORDER BYe HAVING.

E existem desvantagens em vez de fazer "WHERE 1" (escrevendo a definição inteira em vez de um nome de coluna)

Se sua expressão calculada não contiver agregados, colocá-la na WHEREcláusula provavelmente será mais eficiente.

Quassnoi
fonte
289

Todas as outras respostas sobre esta questão não atingiram o ponto principal.

Suponha que temos uma tabela:

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

E tenha 10 linhas com o ID e o valor de 1 a 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);

Tente as 2 consultas a seguir:

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

Você obterá exatamente os mesmos resultados, poderá ver que a cláusula HAVING pode funcionar sem a cláusula GROUP BY.


Aqui está a diferença:

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

Erro # 1054 - coluna desconhecida 'v' na 'cláusula where'

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

A cláusula WHERE permite que uma condição use qualquer coluna da tabela, mas não pode usar aliases ou funções agregadas. A cláusula HAVING permite que uma condição use uma coluna (!) Selecionada, alias ou uma função agregada.

Isso ocorre porque a cláusula WHERE filtra os dados antes da seleção, mas a cláusula HAVING filtra os dados resultantes após a seleção.

Portanto, coloque as condições na cláusula WHERE serão mais eficientes se você tiver muitas linhas em uma tabela.

Tente EXPLAIN para ver a principal diferença:

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

Você pode ver WHERE ou HAVING usa índice, mas as linhas são diferentes.

Fishdrowned
fonte
32
Compreendo que você tenha mencionado EXPLAIN!
paiego 6/12/13
Devido à cláusula HAVING filtrar os dados após a seleção, a cláusula WHERE será mais eficaz. Portanto, se isso for verdade, quando devemos usar HAVING em vez de WHERE?
grep
5
@grep No caso de você precisar filtrar os dados após a seleção, você precisa da cláusula HAVING, normalmente a usamos com a cláusula GROUP BY, por exemplo: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned
1
Excelente post. Alguns esclarecimentos sugeridos: Alterar ...HAVING clause can use both column and alias.para ...HAVING clause can use either column or alias.e alterar ...WHERE clause will be more effectivepara...WHERE clause will be more efficient
rmirabelle
2
A cláusula HAVING foi adicionada ao SQL porque a palavra-chave WHERE não pôde ser usada com funções agregadas.
Shashank Vivek
62

A principal diferença é que WHEREnão pode ser usado em itens agrupados (como SUM(number)) enquanto HAVINGcan.

O motivo é que WHEREé feito antes do agrupamento e HAVINGé feito depois que o agrupamento é concluído.

David Brunelle
fonte
39

HAVINGé usado para filtrar agregações no seu GROUP BY.

Por exemplo, para verificar nomes duplicados:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin
fonte
1
É verdade para alguns existentes. Você ainda pode colocar todo o seu 'Where' na cláusula having.
David Brunelle 25/05
Consulte também stackoverflow.com/questions/2905292/…
Pacerier
8

Esses 2 parecerão iguais aos primeiros, pois ambos são usados ​​para dizer sobre uma condição para filtrar dados. Embora possamos usar 'ter' no lugar de 'onde', em qualquer caso, há casos em que não podemos usar 'onde' em vez de 'ter'. Isso ocorre porque, em uma consulta de seleção, 'onde' filtra os dados antes de 'selecionar' enquanto 'possui' filtrar dados após 'selecionar'. Portanto, quando usamos nomes alternativos que não estão realmente no banco de dados, 'onde' não pode identificá-los, mas 'tendo' pode.

Ex: deixe a tabela Aluno conter student_id, nome, data de nascimento, endereço. Suponha que aniversário seja do tipo data.

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.*/
Nuwantha
fonte
1
Este exemplo da vida real esclarece completamente a diferença entre WHEREe HAVING.
WM
Mostra claramente a diferença entre Ter e onde. Obrigado.
MarcoZen 27/05
3

WHERE filtra antes dos dados serem agrupados e HAVING filtra depois que os dados são agrupados. Esta é uma distinção importante; linhas que são eliminadas por uma cláusula WHERE não serão incluídas no grupo. Isso pode alterar os valores calculados que, por sua vez (= como resultado), podem afetar quais grupos são filtrados com base no uso desses valores na cláusula HAVING .

E continua,

HAVING é tão semelhante a WHERE que a maioria dos DBMSs os trata como a mesma coisa se nenhum GROUP BY for especificado. No entanto, você mesmo deve fazer essa distinção. Use HAVING apenas em conjunto com as cláusulas GROUP BY . Use WHERE para filtragem no nível de linha padrão.

Trecho de: Forta, Ben. “Sams Ensina-se SQL em 10 Minutos (5ª Edição) (Sams Ensina-se ...).”.

snr
fonte
1

Ter é usado apenas com agregação, mas onde com instruções de não agregação Se você tiver onde a palavra a coloca antes da agregação (agrupar por)

Hos Mercury
fonte