Почему эти два, казалось бы, похожих запроса MySQL возвращают радикально разные результаты?

#mysql #clause

#mysql #предложение

Вопрос:

Я хочу получить список модулей, общий рейтинг которых меньше 4. Первый запрос возвращает 1760 строк с данными, которые, похоже, проверяются при перекрестных ссылках. Второй запрос возвращает только 434 строки. Почему это должно быть? Я не до конца понимаю предложения «Group By» и «Having», поэтому я предполагаю, что это как-то связано с ними.

 '''
SELECT u.unitid
,AVG(r.overall) AS AverageRating
, u.ratingcount

FROM reviews r

LEFT JOIN units u
ON u.unitid = r.unitid

-- only retrieve active, non-terminated units set to display
WHERE u.active = 1
AND u.display = 1
AND u.terminated = 0

GROUP BY u.unitid

HAVING AverageRating < 4
;
```
```
SELECT u.UnitID
, u.rating
, u.ratingcount

from units u

WHERE u.rating < 4

-- only retrieve active, non-terminated units set to display
and u.active = 1
and u.display = 1
and u.terminated = 0
;
```
  

Ответ №1:

Ваш первый запрос просматривает все записи и вычисляет среднюю оценку по идентификатору объекта, а затем HAVING предложение ограничивает конечный результат записями, в которых средняя оценка по идентификатору объекта меньше 4.

В вашем втором запросе перечислены все записи, рейтинг которых меньше 4, и это все, что он делает. Это ничего не усредняет.

Вот пара сносных руководств, которые я нашел с помощью быстрого поиска в Google:

HAVING фильтрует агрегированные значения, такие как SUM , AVG , MIN , MAX и т.д. Это похоже на WHERE , но WHERE только фильтрует не агрегированные значения. Вы можете сделать это:

 SELECT UnitId, AVG(Rating)
FROM MyTable
GROUP BY UnitId
HAVING AVG(Rating) < 4 -- Good: HAVING is for filtering on aggregate values
  

Но вы не можете этого сделать (единственное отличие от приведенного выше — это WHERE вместо HAVING в последней строке):

 SELECT UnitId, AVG(Rating)
FROM MyTable
GROUP BY UnitId
WHERE AVG(Rating) < 4 -- Bad: WHERE is for the raw values, before they're aggregated
  

Продолжайте в том же духе. Вы доберетесь туда 🙂

Комментарии:

1. Спасибо за ваш ответ Ed!