我有3张桌子,如下所示:
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
表中每个浣熊都有行(由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)
正如您在上面所看到的,查询没有为ID为4和6的Raccoons返回0
,它只是返回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 |
+----+------------------+----------------------------------------------------------------------------------------------------+--------+
答案 0 :(得分:4)
在子查询之外使用IFNULL
因为它将返回null,因为外表上不匹配,
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;
答案 1 :(得分:1)
您不希望子查询中有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;
另外:当您有相关子查询时,始终使用限定列名。这是防止将来出现问题的良好做法。
答案 2 :(得分:0)
您可以使用内置函数COALESCE()来尝试以下SQL语句:
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;
(抱歉,我不知道如何发布此查询的输出,然后我拍了一张截图: - )
希望这会有所帮助。