ГДЕ против

248

Почему вам нужно размещать столбцы, которые вы создаете сами (например select 1 as "number") после, HAVINGа не WHEREв MySQL?

И есть ли недостатки вместо того, чтобы делать WHERE 1(писать полное определение вместо имени столбца)?

Балу
источник

Ответы:

323

Почему вам нужно разместить столбцы, которые вы создаете сами (например, «выберите 1 как число») после HAVING, а не WHERE в MySQL?

WHEREприменяется до GROUP BY, HAVINGприменяется после (и может фильтровать по агрегатам).

В общем, вы можете ссылаться на псевдонимы ни в одном из этих разделов, но MySQLпозволяет ссылаться на SELECTпсевдонимы уровней в GROUP BY, ORDER BYи HAVING.

И есть ли недостатки, вместо того, чтобы делать «ГДЕ 1» (писать полное определение вместо имени столбца)

Если ваше вычисленное выражение не содержит каких-либо агрегатов, то включение его в WHEREпредложение, скорее всего, будет более эффективным.

Quassnoi
источник
290

Все остальные ответы на этот вопрос не затронули ключевой момент.

Предположим, у нас есть таблица:

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 строк с идентификатором и значением от 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 - неизвестный столбец «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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Вы можете видеть, ГДЕ или ХЭВИНГ использует индекс, но строки разные.

Fishdrowned
источник
32
Я ценю, что вы упомянули EXPLAIN!
Paiego
Из-за того, что предложение HAVING фильтрует данные после выбора, предложение WHERE будет более эффективным. Так что, если это правда, когда мы должны использовать HAVING вместо WHERE?
grep
5
@grep В случае, если вам нужно отфильтровать данные после выбора, вам нужно предложение HAVING, обычно мы используем его с предложением GROUP BY, например: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned
1
Отличный пост. Несколько предложенных разъяснений: Изменение ...HAVING clause can use both column and alias.на ...HAVING clause can use either column or alias.и изменение ...WHERE clause will be more effectiveна...WHERE clause will be more efficient
rmirabelle
2
Предложение HAVING было добавлено в SQL, поскольку ключевое слово WHERE не может использоваться с агрегатными функциями.
Шашанк Вивек
62

Основное отличие состоит в том, что WHEREнельзя использовать сгруппированный элемент (например, SUM(number)), тогда как HAVINGможно.

Причина в том, WHEREделается перед тем группирования и HAVINGделается после того, как группировка делается.

Дэвид Брунелле
источник
39

HAVINGиспользуется для фильтрации по агрегатам в вашем GROUP BY.

Например, чтобы проверить дубликаты имен:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Кевин МакКелвин
источник
1
Это правда для некоторых дошедших до нас. Вы все еще можете поместить все свое «Где» в предложении о наличии.
Дэвид Брунел
Также см stackoverflow.com/questions/2905292/...
Pacerier
8

Эти 2 будут восприниматься так же, как и первые, поскольку оба используются для обозначения условия фильтрации данных. Хотя в любом случае мы можем использовать «иметь» вместо «где», бывают случаи, когда мы не можем использовать «где» вместо «иметь». Это связано с тем, что в запросе выбора «где» фильтрует данные до «выбора», а «фильтрует данные после« выбора ». Таким образом, когда мы используем псевдонимы, которых на самом деле нет в базе данных, «где» не может их идентифицировать, но «иметь» может.

Пример: пусть таблица Student содержит идентификатор студента, имя, день рождения, адрес. Предположим, день рождения имеет тип date.

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
источник
1
Этот пример из реальной жизни полностью проясняет разницу между WHEREи HAVING.
WM
Четко показывает разницу между Иметь и где. Спасибо.
MarcoZen
3

WHERE фильтрует данные перед группировкой, а HAVING - после группировки данных. Это важное различие; строки, которые исключены предложением WHERE , не будут включены в группу. Это может изменить вычисленные значения, что, в свою очередь (= как результат), может повлиять на то, какие группы фильтруются на основе использования этих значений в предложении HAVING .

И продолжает,

HAVING настолько похож на WHERE, что большинство СУБД рассматривают их как одно и то же, если не указан параметр GROUP BY . Тем не менее, вы должны сделать это различие самостоятельно. Используйте HAVING только в сочетании с предложениями GROUP BY . Используйте WHERE для стандартной фильтрации на уровне строк.

Отрывок из: Форта, Бен. «Самс научит себя SQL за 10 минут (5-е издание) (Самс учит себя ...)».

ОСШ
источник
1

Наличие используется только с агрегацией, но где с неагрегированными операторами. Если у вас есть, где слово помещается перед агрегацией (сгруппировать по)

Хос Меркурий
источник