MySQL Group By и HAVING - PullRequest
       74

MySQL Group By и HAVING

6 голосов
/ 23 июня 2011

Я запрос на MySQL, поэтому уверен, что это вопрос с очевидным ответом.

Но я смотрел на эти два запроса. Будут ли они возвращать разные наборы результатов? Я понимаю, что процесс сортировки начнется по-другому, но я верю, что они будут возвращать те же результаты, а первый запрос будет несколько более эффективным?

Запрос 1: ЕСТЬ, потом И

SELECT user_id   
FROM forum_posts  
GROUP BY user_id 
    HAVING COUNT(id) >= 100   
    AND user_id NOT IN (SELECT user_id FROM banned_users)

Запрос 2: ГДЕ, ТО ИМЕЕТ

SELECT user_id   
FROM forum_posts 
WHERE user_id NOT IN(SELECT user_id FROM banned_users) 
GROUP BY user_id 
    HAVING COUNT(id) >= 100   

Ответы [ 5 ]

2 голосов
/ 23 июня 2011

На самом деле первый запрос будет менее эффективным (HAVING применяется после WHERE).
UPDATE

Некоторый псевдокод для иллюстрации того, как выполняются ваши запросы ([очень] упрощенная версия).
Первый запрос:
1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3. Группа, количество и т. Д.
4. Исключить записи из первого набора результатов, если они представлены во втором

Второй запрос
1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3. Исключить записи из первого набора результатов, если они представлены во втором
4. Группа, количество и т. Д.

Порядок шагов 1,2 не важен, mysql может выбрать то, что он считает лучше. Важное отличие заключается в шагах 3,4. После применения GROUP BY. Группировка обычно обходится дороже, чем объединение (исключая записи, которые в данном случае могут рассматриваться как операции объединения), поэтому, чем меньше записей нужно сгруппировать, тем выше производительность.

0 голосов
/ 23 июня 2011

У вас уже есть ответы, что два запроса будут показывать одинаковые результаты и различные мнения, для которых один является более эффективным.

Мое мнение состоит в том, что будет разница в эффективности (скорость), только в том случае, если оптимизатор даст разные планы для 2 запросов. Я думаю, что для последних версий MySQL оптимизаторы достаточно умны, чтобы найти один и тот же план для любого запроса, поэтому не будет никакой разницы , но, конечно, можно протестировать и увидеть либо планы выполнения с EXPLAIN или выполнение 2 запросов к некоторым тестовым таблицам.

Я бы в любом случае использовал вторую версию, просто чтобы быть в безопасности.


Позвольте мне добавить, что:

  • COUNT(*) обычно более эффективен, чем COUNT(notNullableField) в MySQL. Пока это не будет исправлено в будущих версиях MySQL, используйте COUNT(*), где это применимо.

Поэтому вы также можете использовать:

SELECT user_id   
FROM forum_posts 
WHERE user_id NOT IN
  ( SELECT user_id FROM banned_users ) 
GROUP BY user_id 
HAVING COUNT(*) >= 100   
  • Существуют и другие способы достижения тех же (до NOT IN) промежуточных результатов перед применением GROUP BY.

Использование LEFT JOIN / NULL:

SELECT fp.user_id   
FROM forum_posts AS fp
  LEFT JOIN banned_users AS bu
    ON bu.user_id = fp.user_id
WHERE bu.user_id IS NULL 
GROUP BY fp.user_id 
HAVING COUNT(*) >= 100  

Использование NOT EXISTS:

SELECT fp.user_id   
FROM forum_posts AS fp 
WHERE NOT EXISTS
  ( SELECT * 
    FROM banned_users AS bu
    WHERE bu.user_id = fp.user_id
  ) 
GROUP BY fp.user_id 
HAVING COUNT(*) >= 100   

Какой из 3 методов быстрее, зависит от размеров таблицы и множества других факторов, поэтому лучше всего проверить свои данные.

0 голосов
/ 23 июня 2011

Для меня второй запрос более эффективен, поскольку он уменьшает количество записей для GROUP BY и HAVING.

Кроме того, вы можете попробовать следующий запрос, чтобы избежать использования IN:

SELECT `fp`.`user_id`
FROM `forum_posts` `fp`
LEFT JOIN `banned_users` `bu` ON `fp`.`user_id` = `bu`.`user_id`
WHERE `bu`.`user_id` IS NULL
GROUP BY `fp`.`user_id`
HAVING COUNT(`fp`.`id`) >= 100

Надеюсь, это поможет.

0 голосов
/ 23 июня 2011

Нет, это не дает тот же результат.

Поскольку первый запрос фильтрует записи по условию count (id)

Другие записи фильтра запросов и затем применение с предложением.

Второй запрос правильно написан

0 голосов
/ 23 июня 2011

Условия HAVING применяются к , сгруппированным по результатам , и поскольку вы группируете по user_id, все их возможные значения будут присутствовать в сгруппированном результате, поэтому размещение условия user_id не имеет значения.

...