Відповіді:
Чому саме після розміщення HAVING потрібно розміщувати стовпці, які ви створюєте самі (наприклад, "виберіть 1 як число"), а не ДЕ в MySQL?
WHERE
застосовується раніше GROUP BY
, HAVING
застосовується після (і може фільтрувати на агрегатах).
Загалом, ви можете посилатися на псевдоніми ні в одному з цих пунктів, але MySQL
дозволяє посилання SELECT
псевдоніми рівня в GROUP BY
, ORDER BY
і HAVING
.
І чи є якісь мінуси замість того, щоб робити "WHERE 1" (написання цілого визначення замість імені стовпця)
Якщо ваш обчислений вираз не містить сукупностей, введення його в WHERE
пункт, швидше за все, буде більш ефективним.
Усі інші відповіді на це питання не вплинули на ключовий момент.
Припустимо, у нас є таблиця:
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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
Ви можете бачити, де ТІЛЬКО або ВІДПОВІСТЬ використовує індекс, але рядки різні.
SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
...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
Основна відмінність полягає в тому, що WHERE
їх не можна використовувати для згрупованих елементів (таких як SUM(number)
), тоді як HAVING
можуть.
Причиною є те WHERE
, що робиться перед групуванням і HAVING
робиться після групування.
HAVING
використовується для фільтрації на агрегації у вашому GROUP BY
.
Наприклад, щоб перевірити наявність дублікатів імен:
SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Ці 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.*/
WHERE
та HAVING
.
WHERE фільтри перед групуванням даних, і HAVING фільтри після групування даних. Це важлива відмінність; рядки, які усуваються за допомогою пункту WHERE , не включатимуться до групи. Це може змінити обчислені значення, які, у свою чергу (= в результаті), можуть вплинути на те, які групи фільтруються на основі використання цих значень у пункті HAVING .
І продовжує,
HAVING настільки схожий на WHERE, що більшість СУБД трактують їх як одне і те ж, якщо не вказано GROUP BY . Тим не менш, ви повинні зробити це розмежування самостійно. Використовуйте HAVING лише разом із пунктами GROUP BY . Використовуйте WHERE для стандартної фільтрації на рівні рядків.
Уривок: Форта, Бен. "Sams навчає себе SQL за 10 хвилин (5-е видання) (Sams Teach Yourself ...)".
Має використовуватися лише з агрегуванням, але де з операторами, що не містять агрегації