Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Какая разница в скорости работы WHERE и HAVING?
 
 автор: pavluxa09   (29.06.2012 в 00:33)   письмо автору
 
 

Здравствуйте. Что работает быстрее, запрос WHERE (SELECT... FROM ...) = ... либо SELECT (SELECT...) as test HAVING test = ...

И в чём разница между двумя этими операторами? Расскажите пожалуйста. И можно ли их использовать вместе, т.е сначало получить записи с таблицы под выражением WHERE а потом из результатов выбрать нужные при помощи HAVING? если да то как?

  Ответить  
 
 автор: Sfinks   (29.06.2012 в 02:32)   письмо автору
 
   для: pavluxa09   (29.06.2012 в 00:33)
 

1. Скорость ВСЕГДА зависит от данных, структуры БД, типа выборки, индексов и т.д. и.т.п.
Поэтому невозможно сказать что что-либо работает быстрее. В каждом конкретном случае все будет по разному.

2. Сравнивать where и having мягко говоря не корректно.
Они хоть и похожи, но только тем, что оба что-то отсеивают. Но это разные вещи.

> И в чём разница между двумя этими операторами?
where работает до группировки, второй после группировки и самого селекта.
Т.е. в where можно проверять значения исходной таблицы, а в having результаты выборки и использовать агрегатные функции.

> И можно ли их использовать вместе
Да, можно.

> если да то как?
Например так:
SELECT id, sum(out) as sum_out FROM table
WHERE id IN (1,4,7,8,9)
GROUP BY id
HAVING max(change_date) = '2012-06-20' AND sum_out >= 100

В этом запросе порядок действий будет такой:
1. FROM (выбирается вся таблица table);
2. WHERE (отбрасываются все строки, id которых не равно 1,4,7,8 или 9);
3. GROUP BY (строки разбиваются на группы с одинаковым id);
4. SELECT (Для каждой группы вычисляется sum(out) с алиасом sum_out);
5. HAVING (отбрасываются группы строк, в которых max(change_date) внутри группы не равно заданной дате, из оставшегося выбрасываются группы в которых sum_out меньше 100).

P.S. Я написал в начале, что "сравнивать не корректно", потому что само-собой все что может быть в where должно быть в where. В having должно быть то, что быть в where не может.
Ну а наоборот вам и сам Мускул не позволит сделать и, если вы попытаетесь написать WHERE max(change_date) = '2012-06-20', выдаст ошибку

  Ответить  
 
 автор: pavluxa09   (29.06.2012 в 10:25)   письмо автору
 
   для: Sfinks   (29.06.2012 в 02:32)
 

Супер. Спасибо большое, разобрался что к чему!

  Ответить  
 
 автор: pavluxa09   (29.06.2012 в 10:32)   письмо автору
 
   для: pavluxa09   (29.06.2012 в 10:25)
 

Помогите пожалуйста разрабраться с моим случаем. Я делаю поиск по таблице, мне нужно отсеить значения через WHERE и HAVING одновременно. Получается запрос вида:

SELECT SQL_CALC_FOUND_ROWS
     `ID`,
     `betAmount`,
     `betCurrency`,
     IF(1 = `serverID`, TRUE, FALSE) as `isServer`,
     `serverID`,
     IF(1 = `serverID`, NULL, 
       (SELECT `nickName` FROM `XeronUsers`
        WHERE `ID` = `XeronKNB`.`serverID`)) as `serverNick`,
     `serverObject`,
     `playedDate` as `originalPlayedDate`,
     DATE_FORMAT(`playedDate`, '%d.%m.%Y %H:%i') as `playedDate`,
     `clientID`,
     `clientObject`,
     `winner`
FROM `XeronKNB`
WHERE
  `status` = 1 AND
  (`ID` LIKE '%1%' OR
   `playedDate` LIKE '%1%' OR
   `betAmount` LIKE '%1%' OR
   `betCurrency` LIKE '%1%' )
HAVING (`serverNick` LIKE '%1%' )
ORDER By `originalPlayedDate` desc
LIMIT 0, 5



Получается такая ситуация, что у нас то что в WHERE не срабатывает, а оно должно взаимодействовать, мне нужно что бы WHERE и HAVING стояли как бы через AND. Т.е должно быть такое ОБЩЕЕ условие выборки:

status = 1 и ([условия с WHERE] или [условия с HAVING])

  Ответить  
 
 автор: Sfinks   (30.06.2012 в 00:51)   письмо автору
 
   для: pavluxa09   (29.06.2012 в 10:32)
 

А зачем у вас (`serverNick` LIKE '%1%') в HAVING?
Подзапросы также можно включать в WHERE.

Т.е. если вы напишите:
....
WHERE IF(1 = `serverID`, NULL,  
       (SELECT `nickName` FROM `XeronUsers` 
        WHERE `ID` = `XeronKNB`.`serverID`)) LIKE '%1%'
ошибки не будет.

Но я бы разложил на два условия для наглядности:
....
WHERE ( serverID <> 1
        AND (SELECT `nickName` FROM `XeronUsers` WHERE `ID` = `XeronKNB`.`serverID`) LIKE '%1%' )
но это уже кому как нравится.

И группируйте его внутри одного только WHERE с другими условиями какими хотите AND'ами и OR'ами.

  Ответить  
 
 автор: pavluxa09   (30.06.2012 в 16:49)   письмо автору
 
   для: Sfinks   (30.06.2012 в 00:51)
 

А подзапрос во where не влияет на скорость работы?

  Ответить  
 
 автор: Sfinks   (30.06.2012 в 19:45)   письмо автору
 
   для: pavluxa09   (30.06.2012 в 16:49)
 

Само собой разумеется, что любой подзапрос увеличивает общее время выполнения.
И, да, подзапрос в WHERE это медленнее, чем подзапрос в SELECT.
Но если у вас отсев происходит по результатам подзапроса, то иначе никак.
Вы же сами 3 поста назад неплохо описали логику: Уже отсеяно, а нужно проверить.
А как вы хотите - это называется - и рыбку съесть, и удовольствие получить =)

Можно приджойнить таблицу `XeronUsers` И делать выборку по объединенной таблице:
.............
FROM `XeronKNB` K
LEFT JOIN `XeronUsers` U ON K.`serverID`<>1 AND U.`ID` = K.`serverID`
WHERE 
  K.`status` = 1 AND 
  (K.`ID` LIKE '%1%' OR 
   K.`playedDate` LIKE '%1%' OR 
   K.`betAmount` LIKE '%1%' OR 
   K.`betCurrency` LIKE '%1%' OR
   U.`nickName` LIKE '%1%' )
............
, но не уверен что это будет быстрее.

  Ответить  
 
 автор: pavluxa09   (03.07.2012 в 18:35)   письмо автору
 
   для: Sfinks   (30.06.2012 в 19:45)
 

Я пишу плагин под Datatables (серверный) и проблема с поиском, некоторые поля это вложенные подзапросы, а по их содержимому необходимо выполнять поиск. Как поступать в этом случае? таблицы содержат по несколько сотен тысяч записей, и использовать под запрос в WHERE работает очень медленно

  Ответить  
 
 автор: Sfinks   (03.07.2012 в 19:13)   письмо автору
 
   для: pavluxa09   (03.07.2012 в 18:35)
 

Менять структуру БД - это раз.
и
Уходить от LIKE'ов, т.к. они крайне медленны - это 2.

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

Имея такую структуру, как у вас сейчас - ниче хорошего не получится. Дальше будет только хуже.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования