|
|
|
| Здравствуйте. Что работает быстрее, запрос WHERE (SELECT... FROM ...) = ... либо SELECT (SELECT...) as test HAVING test = ...
И в чём разница между двумя этими операторами? Расскажите пожалуйста. И можно ли их использовать вместе, т.е сначало получить записи с таблицы под выражением WHERE а потом из результатов выбрать нужные при помощи HAVING? если да то как? | |
|
|
|
|
|
|
|
для: 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', выдаст ошибку | |
|
|
|
|
|
|
|
для: Sfinks
(29.06.2012 в 02: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]) | |
|
|
|
|
|
|
|
для: 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'ами. | |
|
|
|
|
|
|
|
для: Sfinks
(30.06.2012 в 00:51)
| | А подзапрос во where не влияет на скорость работы? | |
|
|
|
|
|
|
|
для: 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%' )
............
| , но не уверен что это будет быстрее. | |
|
|
|
|
|
|
|
для: Sfinks
(30.06.2012 в 19:45)
| | Я пишу плагин под Datatables (серверный) и проблема с поиском, некоторые поля это вложенные подзапросы, а по их содержимому необходимо выполнять поиск. Как поступать в этом случае? таблицы содержат по несколько сотен тысяч записей, и использовать под запрос в WHERE работает очень медленно | |
|
|
|
|
|
|
|
для: pavluxa09
(03.07.2012 в 18:35)
| | Менять структуру БД - это раз.
и
Уходить от LIKE'ов, т.к. они крайне медленны - это 2.
Лучший вариант - чтоб поиск был только по цифрам.
Собстно так и должно быть.
Куча индексированных таблиц связей, в которых только цифры, по которым производятся выборки. А только после этого к ним приджойниваются строки по ключам.
Имея такую структуру, как у вас сейчас - ниче хорошего не получится. Дальше будет только хуже. | |
|
|
|