2015-11-30 2 views
0

У меня есть 3 таблицы, как показано ниже:MySQL AVG() возвращает 0, если NULL

mysql> select * from Raccoon; 
+----+------------------+----------------------------------------------------------------------------------------------------+ 
| id | name    | image_url                       | 
+----+------------------+----------------------------------------------------------------------------------------------------+ 
| 3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png          | 
| 4 | Bobby Coon  | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg          | 
| 5 | Doc Raccoon  | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 | 
| 6 | Eddie the Rac | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg             | 
+----+------------------+----------------------------------------------------------------------------------------------------+ 
4 rows in set (0.00 sec) 

mysql> select * from Review; 
+----+------------+-------------+---------------------------------------------+--------+ 
| id | raccoon_id | reviewer_id | review          | rating | 
+----+------------+-------------+---------------------------------------------+--------+ 
| 1 |   3 |   1 | This raccoon was a fine raccoon indeed.  |  5 | 
| 2 |   5 |   2 | This raccoon did not do much for me at all. |  2 | 
| 3 |   3 |   1 | asdfsadfsadf        |  5 | 
| 4 |   5 |   2 | asdfsadf         |  1 | 
+----+------------+-------------+---------------------------------------------+--------+ 
4 rows in set (0.00 sec) 

mysql> select * from Reviewer; 
+----+---------------+ 
| id | reviewer_name | 
+----+---------------+ 
| 1 | Kane Charles | 
| 2 | Cameron Foale | 
+----+---------------+ 
2 rows in set (0.00 sec) 

Я пытаюсь создать запрос на выборку, которая будет возвращать все столбцы в Raccoon, а также дополнительную колонку который захватывает среднее значение Review.rating (сгруппировано по id). Проблема, с которой я сталкиваюсь, заключается в том, что нет никакой гарантии, что в таблице Review будут присутствовать строки для каждого отдельного Raccoon (как определено FK, raccoon_id, которое ссылается на Raccoon.id. В ситуациях, когда в таблице Review имеются нулевые строки (для данный Raccoon.id, т.е. Review.raccoon_id) Я хотел бы запрос, чтобы вернуть 0 как среднее для этого енота

Ниже приведен текущий запрос я использую:.

mysql> SELECT *, (SELECT IFNULL(AVG(rating),0) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC; 
+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 
| id | name    | image_url                       | AVG | 
+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 
| 3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png          | 5.0000 | 
| 4 | Bobby Coon  | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg          | NULL | 
| 5 | Doc Raccoon  | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 | 1.5000 | 
| 6 | Eddie the Rac | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg             | NULL | 
+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 
4 rows in set (0.00 sec) 

Как вам см. выше, запрос не возвращает 0 для Raccoons с идентификатором 4 и 6, он просто возвращает NULL. Мне нужно, чтобы вернуть что-то вроде следующей (обратите внимание на порядок, отсортированный по самому низкому среднему обзора первого):

+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 
| id | name    | image_url                       | AVG | 
+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 
| 4 | Bobby Coon  | https://c2.staticflickr.com/6/5242/5370143072_dee60d0ce2_n.jpg          | 0.0000 | 
| 6 | Eddie the Rac | http://www.felid.org/jpg/EDDIE%20THE%20RACCOON.jpg             | 0.0000 | 
| 5 | Doc Raccoon  | http://images.encyclopedia.com/utility/image.aspx?id=2801690&imagetype=Manual&height=300&width=300 | 1.5000 | 
| 3 | Jesse Coon James | http://www.pawfun.com/wp/wp-content/uploads/2010/01/rabbid.png          | 5.0000 | 
+----+------------------+----------------------------------------------------------------------------------------------------+--------+ 

ответ

3

использование IFNULL за пределами подзапроса, так как он будет возвращать нуль его там не совпадает на внешних таблицах,

IFNULL((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG" 

Или вы можете также использовать LEFT JOIN,

SELECT ra.id, ra.name, ra.image_url, 
     IFNULL(AVG(rv.rating),0)AS "AVG" 
FROM Raccoon ra 
     LEFT JOIN Review rv 
      ON rv.raccoon_id = ra.id 
GROUP BY ra.id, ra.name, ra.image_url 
ORDER BY "AVG" ASC; 
0

вы не хотите в подзапрос с group by. Это опасно, потому что он может возвращать более одного ряда (хотя where предотвращает это). Что еще более важно, без group by подзапрос представляет собой запрос агрегации, который всегда возвращает одну строку. Таким образом, вы можете поместить логику в подзапрос:

SELECT r.*, 
     (SELECT COALESCE(AVG(rev.rating),0) 
     FROM Review rev 
     WHERE rev.raccoon_id = r.id 
     ) AS "AVG" 
FROM Raccoon r 
ORDER BY "AVG" ASC; 

также: всегда использовать квалифицированные имена столбцов, когда у вас есть связанный подзапрос. Это хорошая практика для предотвращения проблем в будущем.

0

Вы можете попробовать следующее SQL заявление с встроенной функцией COALESCE():

SELECT *, COALESCE((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC; 

Вы можете найти в руководстве по эксплуатации этой функции here.

Если вы предпочитаете использовать IFNULL, вы можете использовать

SELECT *, IFNULL((SELECT AVG(rating) FROM Review WHERE raccoon_id=Raccoon.id GROUP BY raccoon_id), 0) AS "AVG" FROM Raccoon ORDER BY "AVG" ASC; 

Похоже, вы поняли сферу функций.

Однако, я думаю, что лучший способ заключается в использовании левых внешнего соединения, вместо подзапроса, вот запрос я написал для справки:

select Raccoon.id, Raccoon.name, Raccoon.image_url, IFNULL(AVG(rating),0) avg from Raccoon LEFT OUTER join Review ON raccoon_id =Raccoon.id GROUP BY raccoon.id ORDER BY AVG ASC; 

Тогда вы получите следующие результаты: enter image description here

(жаль, что я не знаю, как я могу отправить вывод этого запроса, то я взял скриншот :-)

Надеется, что это поможет.

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