ГДЕ проти НЕБЕ


247

Чому потрібно розміщувати стовпці, які ви створюєте самі (наприклад select 1 as "number") після, HAVINGа не WHEREв MySQL?

І чи є якісь мінуси замість цього WHERE 1(написати ціле визначення замість імені стовпця)?

Відповіді:


323

Чому саме після розміщення HAVING потрібно розміщувати стовпці, які ви створюєте самі (наприклад, "виберіть 1 як число"), а не ДЕ в MySQL?

WHEREзастосовується раніше GROUP BY, HAVINGзастосовується після (і може фільтрувати на агрегатах).

Загалом, ви можете посилатися на псевдоніми ні в одному з цих пунктів, але MySQLдозволяє посилання SELECTпсевдоніми рівня в GROUP BY, ORDER BYі HAVING.

І чи є якісь мінуси замість того, щоб робити "WHERE 1" (написання цілого визначення замість імені стовпця)

Якщо ваш обчислений вираз не містить сукупностей, введення його в WHEREпункт, швидше за все, буде більш ефективним.


289

Усі інші відповіді на це питання не вплинули на ключовий момент.

Припустимо, у нас є таблиця:

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' in 'where clause'

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

Стаття WHERE дозволяє умові використовувати будь-який стовпець таблиці, але він не може використовувати псевдоніми або агрегатні функції. Стаття HAVING дозволяє умові використовувати вибраний (!) Стовпчик, псевдонім або сукупну функцію.

Це тому, що пункт WHERE фільтрує дані перед вибором, але HAVING пропозиція фільтрує результати після вибору.

Тому помістіть умови в пункт WHERE буде ефективніше, якщо у вас буде багато багато рядків у таблиці.

Спробуйте пояснити, щоб побачити ключову різницю:

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

Ви можете бачити, де ТІЛЬКО або ВІДПОВІСТЬ використовує індекс, але рядки різні.


32
Я вдячний, що ви згадали ПОЯСНЕННЯ!
paiego

Через те, що пункт HAVING фільтрує дані після вибору, пункт WHERE буде більш ефективним. Отже, якщо це правда, коли ми повинні використовувати HAVING замість ДЕ?
греп

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
У SQL було додано пропозицію HAVING, оскільки ключове слово WHERE не можна було використовувати з агрегатними функціями.
Шашанк Вівек

62

Основна відмінність полягає в тому, що WHEREїх не можна використовувати для згрупованих елементів (таких як SUM(number)), тоді як HAVINGможуть.

Причиною є те WHERE, що робиться перед групуванням і HAVINGробиться після групування.


39

HAVINGвикористовується для фільтрації на агрегації у вашому GROUP BY.

Наприклад, щоб перевірити наявність дублікатів імен:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1

1
Це правда для деяких існуючих. Ви все ще можете поставити ціле "Де" у відповідному пункті.
Девід Брунелль


8

Ці 2 будуть відчувати себе так само, як і перші, оскільки обидва використовуються для того, щоб говорити про умову фільтрації даних. Хоча ми можемо використовувати "маючи" замість "де" у будь-якому випадку, є випадки, коли ми не можемо використовувати "де", а не "мати". Це пояснюється тим, що у запиті вибору "де" фільтрує дані до "вибору", а "фільтрує дані після" вибору ". Отже, коли ми використовуємо імена псевдонімів, яких насправді немає в базі даних, "де" їх не можна ідентифікувати, але "маючи".

Наприклад: нехай таблиця Student містить студент_id, ім'я, день народження, адресу.

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.*/

1
Цей приклад із реального життя повністю роз’яснює різницю між WHEREта HAVING.
WM

Чітко показує різницю між наявністю та де. Дякую.
MarcoZen

3

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

І продовжує,

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

Уривок: Форта, Бен. "Sams навчає себе SQL за 10 хвилин (5-е видання) (Sams Teach Yourself ...)".


1

Має використовуватися лише з агрегуванням, але де з операторами, що не містять агрегації

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.