2016-09-06 2 views
1

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

Документы MySQL имеют этот комментарий. «Стандарт SQL требует, чтобы HAVING должен ссылаться только на столбцы в предложении GROUP BY или в столбцах, используемых в агрегатных функциях».

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

Всегда ли (или полезно) для неагрегированных сгруппированных столбцов?

Благодаря

+1

Что вы подразумеваете под «неагрегированными группируемыми столбцами?» Пример? –

+0

Я попытался использовать его (на SQL Server) для обмана оптимизатора, чтобы отложить оценку некоторых условий. Я не помню специфику. И хотя я помню, как вижу различия в плане исполнения, я не думаю, что это дало мне результат, на который я надеялся. – shawnt00

+1

@ExplosionPills OP означает (я думаю), что в предложении select есть неагрегированные столбцы, которые мы также группируем и включаем в них условия, содержащие предложение. –

ответ

4

HAVING специально разработан для агрегированных колонн. MySQL позволяет неагрегированные столбцы в предложении HAVING. Существует три варианта использования:

  1. Эффективность взлома, когда значения группы имеют одинаковые значения для группы.
  2. Ошибка, которой следует избегать.
  3. Эффективность взлома, когда нет агрегации.

Первый предположительно может быть использован в ситуации, как это:

select l.*, sum(x.y) 
from list l join 
    . . . 
group by l.listid 
having l.foo = 'bar'; 

Это работает, потому что все l.foo должны иметь одинаковое значение для данного l.listid (предполагается, что l.listid является первичным ключом). В этом случае это фильтрует данные, как если бы вы использовали where.

НО, если это условие неверно, эквивалентность эквивалента не соответствует действительности. HAVING выберет значение из неопределенной строки и затем фильтрует полученный столбец агрегации. WHERE выполняет фильтрацию перед агрегацией. Таким образом, если списки могут иметь один и тот же тип и вы:

select l.*, sum(x.y) 
from list l join 
    . . . 
group by l.type 
having l.foo = 'bar'; 

Это плохо формируется запрос (отсюда ошибка, на мой взгляд), но не эквивалентно перемещению условие к WHERE.

Третья ситуация, когда нет агрегации:

select l.*, concat('a', 'b', 'c') as test 
from list l 
having test = 'abc'; 

Это удобство в MySQL. Другие диалекты будут использовать подзапрос.MySQL материализует подзапросы, внедряя неэффективность.

+0

Этот ответ дает большое представление о том, что касается MySQL. Обычно инженеры базы данных и sql ninjas советуют не использовать неагрегированные столбцы в предложении select, несмотря на то, что этот движок позволяет вам. –

+0

Отличные примеры, спасибо – rimsky

1

No.

WHERE условие применяется до строки сгруппированы, HAVING применяется сгруппированных строк. Если не используется агрегированный столбец, вы выбираете на основе значения одной строки в любом случае, поэтому единственная (семантическая) разница заключается в том, будут ли строки выбраны до группировки или после нее, - но результат будет таким же.

(Обратите внимание, что эта разница может даже не быть правдой на практике, оптимизатор может изменять порядок операций.)

Смежные вопросы